2020-12-12 Daily-Challenge

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

LeetCode Review

Jump Game II

smaller constant $O(n)$ solution

class Solution {
public:
    int jump(vector<int>& nums) {
        int len = nums.size();
        if(len == 1) return 0;
        if(len-1 <= nums[0]) return 1;
        int farthest = -1;
        int nextJump = nums[0];
        int jump = 1;
        for(int i = 1; i < len; ++i) {
            farthest = max(farthest, i + nums[i]);
            if(i == nextJump) {
                jump += 1;
                nextJump = farthest;
            }
            if(nextJump >= len-1) break;
        }
        return jump;
    }
};

Remove Duplicates from Sorted Array II

use just one variable for position

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int len = nums.size();
        if(len < 3) return len;
        int removePos = 2;
        int pos = 1;
        for( ;removePos < len; ++removePos, ++pos) {
            while(removePos < len && nums[removePos] == nums[pos-1]) removePos +=1;
            if(removePos == len) break;
            swap(nums[pos+1], nums[removePos]);
        }
        nums.resize(pos+1);
        return pos+1;
    }
};

Path with Maximum Probability

bellman ford algorithm

class Solution {
public:
    double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start, int end) {
        vector<double> distance(n);
        distance[start] = 1;
        int len = edges.size();
        for(int loop = 0; loop < len; ++loop) {
            bool modified = false;
            for(int i = 0; i < len; ++i) {
                int a = edges[i][0];
                int b = edges[i][1];
                double prob = succProb[i];
                if(distance[b]*prob > distance[a]) {
                    distance[a] = distance[b]*prob;
                    modified = true;
                }
                if(distance[a]*prob > distance[b]) {
                    distance[b] = distance[a]*prob;
                    modified = true;
                }
            }
            if(!modified) break;
        }
        return distance[end];
    }
};

Valid Mountain Array

nothing to say

class Solution {
public:
    bool validMountainArray(vector<int>& arr) {
        int len = arr.size();
        if(len < 3 || arr[1] <= arr[0]) return false;
        int pos = 1;
        while(pos < len && arr[pos] > arr[pos-1]) ++pos;
        if(pos == len) return false;
        while(pos < len && arr[pos] < arr[pos-1]) ++pos;
        return pos == len;
    }
};

Distinct Subsequences

$$ dp[i][j] = \begin{cases} dp[i-1][j] & \text{if s[i] != t[j]}\ dp[i-1][j] + dp[i-1][j-1] & \text{if s[i] == t[j]} \end{cases} $$

using same optimization techniques as backpack problem then we only need one dimension vector.

class Solution {
public:
    int numDistinct(string s, string t) {
        int slen = s.length();
        int tlen = t.length();
        if(slen <= tlen) return s == t;
        vector<long long> dp(tlen+1);
        dp[0] = 1;
        for(int i = 0; i < slen; ++i) {
            int beginPos = max(1, tlen-slen+i);
            int endPos = min(tlen, i+slen-tlen+1);
            for(int j = endPos; j >= beginPos; --j) {
                if(s[i] == t[j-1]) dp[j] += dp[j-1];
            }
        }
        return dp.back();
    }
};

Distinct Subsequences II

nothing to say

class Solution {
public:
    int distinctSubseqII(string S) {
        const int MOD = 1e9+7;
        vector<int> last(26, -1);
        int len = S.length();
        vector<int> dp(len+1);
        dp[0] = 1;
        for(int i = 1; i <= len; ++i) {
            int c = S[i-1] - 'a';
            dp[i] = 2 * dp[i-1];
            dp[i] %= MOD;
            if(last[c] != -1) {
                dp[i] -= dp[last[c]-1];
                if(dp[i] < 0) dp[i] += MOD;
            }
            last[c] = i;
        }
        return dp.back()-1;
    }
};

Binary Search Tree Iterator

morris traversal

class BSTIterator {
    TreeNode *cur, *prev;
public:
    BSTIterator(TreeNode* root) {
        cur = root, prev = nullptr;
    }
    
    int next() {
        int result = -1;
        while(result < 0) {
            if(!cur->left) {
                result = cur->val;
                prev = cur;
                cur = cur->right;
            } else {
                TreeNode *pred = cur->left;
                while(pred->right && pred->right != cur) pred = pred->right;
                if(pred->right) {
                    pred->right = nullptr;
                    result = cur->val;
                    prev = cur;
                    cur = cur->right;
                } else {
                    pred->right = cur;
                    cur = cur->left;
                }
            }
        }
        return result;
    }
    
    bool hasNext() {
        return cur;
    }
};

Minimum Moves to Make Array Complementary

sweeping line

class Solution {
public:
    int minMoves(vector<int>& nums, int limit) {
        vector<int> lines(2*limit+2);
        int len = nums.size();
        for(int i = 0; i*2 < len; ++i) {
            int mmin = min(nums[i], nums[len-1-i]);
            int mmax = max(nums[i], nums[len-1-i]);
            lines[mmin+1] -= 1;
            lines[mmin+mmax] -= 1;
            lines[mmin+mmax+1] += 1;
            lines[mmax+limit+1] += 1;
        }
        int current = len;
        int answer = INT_MAX;
        for(auto i : lines) {
            current += i;
            answer = min(answer, current);
        }
        return answer;
    }
};

Smallest Rotation with Highest Score

add some comment

class Solution {
public:
    int bestRotation(vector<int>& A) {
        int len = A.size();
        vector<int> lines(len);
        for(int i = 0; i < len; ++i) {
            int leastRotate = (i + 1) % len;
            // most rotate is i - A[i] + len, plus one is offset for line
            int mostRotate = (i - A[i] + len + 1) % len;
            lines[leastRotate] += 1;
            lines[mostRotate] -= 1;
            if(leastRotate > mostRotate-1) {
                // rotate range is like [0,1]+[4,5]
                lines[0] += 1;
            }
        }
        int current = 0;
        int highScore = 0;
        int answer = -1;
        for(int i = 0; i < len; ++i) {
            current += lines[i];
            if(current > highScore) {
                highScore = current;
                answer = i;
            }
        }
        return answer;
    }
};

Reduce Array Size to The Half

using vector is slower

class Solution {
public:
    int minSetSize(vector<int>& arr) {
        if(arr.size() < 3) return 1;
        int len = arr.size();
        vector<int> cnt(100001);
        for(auto i : arr) cnt[i] += 1;
        sort(cnt.begin(), cnt.end(), greater<int>());
        int c = 0;
        for(int i = 0; i < 100001; ++i) {
            c += cnt[i];
            if(c*2 >= len) return i+1;
        }
        return -1;
    }
};

Pairs of Songs With Total Durations Divisible by 60

too easy to review

Spiral Matrix II

already reviewed

December LeetCoding Challenge 12

Description

Smallest Subtree with all the Deepest Nodes

Given the root of a binary tree, the depth of each node is the shortest distance to the root.

Return the smallest subtree such that it contains all the deepest nodes in the original tree.

A node is called the deepest if it has the largest depth possible among any node in the entire tree.

The subtree of a node is tree consisting of that node, plus the set of all descendants of that node.

Note: This question is the same as 1123: https://leetcode.com/problems/lowest-common-ancestor-of-deepest-leaves/

Example 1:

img

Input: root = [3,5,1,6,2,0,8,null,null,7,4]
Output: [2,7,4]
Explanation: We return the node with value 2, colored in yellow in the diagram.
The nodes coloured in blue are the deepest nodes of the tree.
Notice that nodes 5, 3 and 2 contain the deepest nodes in the tree but node 2 is the smallest subtree among them, so we return it.

Example 2:

Input: root = [1]
Output: [1]
Explanation: The root is the deepest node in the tree.

Example 3:

Input: root = [0,1,3,null,2]
Output: [2]
Explanation: The deepest node in the tree is 2, the valid subtrees are the subtrees of nodes 2, 1 and 0 but the subtree of node 2 is the smallest.

Constraints:

  • The number of nodes in the tree will be in the range [1, 500].
  • 0 <= Node.val <= 500
  • The values of the nodes in the tree are unique.

Solution

answer with worst run time and space usage XD

class Solution {
    unordered_map<TreeNode*, TreeNode*> parent;
    vector<TreeNode*> deepest;
    int deepestLevel = -1;
    void findDeepestLevel(TreeNode* root, int curLevel) {
        if(!root) return;
        if(curLevel > deepestLevel) {
            deepestLevel = curLevel;
        }
        parent[root->left] = root;
        parent[root->right] = root;
        findDeepestLevel(root->left, curLevel+1);
        findDeepestLevel(root->right, curLevel+1);
    }
    void findDeepestNodes(TreeNode* root, int curLevel) {
        if(!root) return;
        if(curLevel == deepestLevel) {
            deepest.push_back(root);
        } else {
            findDeepestNodes(root->left, curLevel+1);
            findDeepestNodes(root->right, curLevel+1);
        }
    }
public:
    TreeNode* subtreeWithAllDeepest(TreeNode* root) {
        if(!root) return root;
        findDeepestLevel(root, 0);
        findDeepestNodes(root, 0);
        if(deepest.size() == 1) return deepest.front();
        unordered_map<TreeNode*, int> cur;
        unordered_map<TreeNode*, int> nxt;
        for(auto node : deepest) {
            cur[parent[node]] += 1;
        }
        while(cur.size() > 1) {
            nxt.clear();
            for(auto [node, _] : cur) {
                nxt[parent[node]] += 1;
            }
            cur = nxt;
        }
        return cur.begin()->first;
    }
};