2021-06-13 Daily-Challenge

Today is Saturday, I gonna review the tasks I've done this week, and finish today's leetcode's June LeetCoding Challenge with cpp.

LeetCode Review

My Calendar I

class MyCalendar {
  set<pair<int, int>> times;
public:
  MyCalendar(){}
  
  bool book(int start, int end) {
    auto it = times.upper_bound({start, end});
    if(it != times.end() && it->second < end) return false;
    times.insert({end, start});
    return true;
  }
};

Stone Game VII

class Solution {
public:
  int stoneGameVII(vector<int>& stones) {
    int len = stones.size();
    int prefix[len + 1];
    prefix[0] = 0;
    for (int i = 0; i < len; ++i) prefix[i + 1] = prefix[i] + stones[i];
    int dp[len + 1][len + 1];
    memset(dp, 0, sizeof(dp));
    for (int i = 1; i <= len; ++i) {
      for(int j = 0; j + i <= len; ++j) {
        int left = prefix[j + i - 1] - prefix[j] - dp[j][j + i - 1];
        int right = prefix[j + i] - prefix[j + 1] - dp[j + 1][j + i];
        dp[j][j + i] = max(left, right);
        // cout << j << ' ' << j << ' ' << dp[j][j + i] << endl;
      }
    }
    return dp[0][len];
  }
};


68 / 68 test cases passed.
Status: Accepted
Runtime: 136 ms
Memory Usage: 14 MB

optimize using locality, seems useless

class Solution {
public:
  int stoneGameVII(vector<int>& stones) {
    int len = stones.size();
    int prefix[len + 1];
    prefix[0] = 0;
    for (int i = 0; i < len; ++i) prefix[i + 1] = prefix[i] + stones[i];
    int dp[len + 1][len + 1];
    memset(dp, 0, sizeof(dp));
    for (int l = len - 1; l >= 0; --l) {
      for(int r = l + 1; r <= len; ++r) {
        int left = prefix[r - 1] - prefix[l] - dp[l][r - 1];
        int right = prefix[r] - prefix[l + 1] - dp[l + 1][r];
        dp[l][r] = max(left, right);
        // cout << j << ' ' << j << ' ' << dp[j][j + i] << endl;
      }
    }
    return dp[0][len];
  }
};

// 68 / 68 test cases passed.
// Status: Accepted
// Runtime: 160 ms
// Memory Usage: 14.1 MB

June LeetCoding Challenge 13

Description

Palindrome Pairs

Given a list of unique words, return all the pairs of the *distinct* indices (i, j) in the given list, so that the concatenation of the two words words[i] + words[j] is a palindrome.

Example 1:

Input: words = ["abcd","dcba","lls","s","sssll"]
Output: [[0,1],[1,0],[3,2],[2,4]]
Explanation: The palindromes are ["dcbaabcd","abcddcba","slls","llssssll"]

Example 2:

Input: words = ["bat","tab","cat"]
Output: [[0,1],[1,0]]
Explanation: The palindromes are ["battab","tabbat"]

Example 3:

Input: words = ["a",""]
Output: [[0,1],[1,0]]

Constraints:

  • 1 <= words.length <= 5000
  • 0 <= words[i].length <= 300
  • words[i] consists of lower-case English letters.

Solution

DFS + trie, very clever solution, check An7One's solution

struct TrieNode {
  TrieNode *children[26] = {};
  int index = -1;
  vector<int> palinIndex;
};

inline bool isPalindrome(const string &word, int start, int end) {
  while(start < end) {
    if(word[start] != word[end]) return false;
    start += 1;
    end -= 1;
  }
  return true;
}

void addWord(TrieNode *root, const string &word, int index) {
  int len = word.size();
  auto cur = root;
  for(int i = len - 1; i >= 0; i--) {
    int ch = word[i] - 'a';
    if(!(cur->children[ch])) cur->children[ch] = new TrieNode();
    if(isPalindrome(word, 0, i)) cur->palinIndex.push_back(index);

    cur = cur->children[ch];
  }
  cur->palinIndex.push_back(index);
  cur->index = index;
}

void search(TrieNode *root, vector<string> &words, int index, vector<vector<int>> &answer) {
  auto cur = root;
  auto curWord = words[index];
  int len = curWord.length();

  for(int i = 0; i < len; i++) {
    if(cur->index != -1 && cur->index != index && isPalindrome(curWord, i, len - 1)) {
      answer.push_back({index, cur->index});
    }
    cur = cur->children[curWord[i] - 'a'];
    if(!cur) return;
  }
  for(auto idxPalin : cur->palinIndex) {
    if(idxPalin == index) continue;
    answer.push_back({index, idxPalin});
  }
}

class Solution {
public:
  vector<vector<int>> palindromePairs(vector<string>& words) {
    auto root = new TrieNode();
    int len = words.size();
    vector<vector<int>> answer;

    for(int i = 0; i < words.size(); ++i) addWord(root, words[i], i);
    for(int i = 0; i < words.size(); ++i) search(root, words, i, answer);

    return answer;
  }
};