LeetCode(101-150)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LintaoD/article/details/81741103

LeetCode(101-150)

101. Symmetric Tree(Easy)

  Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

  • Example:
For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
    1
   / \
  2   2
 / \ / \
3  4 4  3
But the following [1,2,2,null,3,null,3] is not:
    1
   / \
  2   2
   \   \
   3    3
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isSym(TreeNode* p,TreeNode* q){
        if(p == NULL || q == NULL)return (p == q);
        return ((p->val == q->val)&&(isSym(p->left,q->right))&&(isSym(p->right,q->left)));
    }
    bool isSymmetric(TreeNode* root) {
        if(root == NULL) return true;
        return isSym(root->left,root->right);
    }
};

102. Binary Tree Level Order Traversal(Medium)

  Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).

  • Example:
For example:
Given binary tree [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7
return its level order traversal as:
[
  [3],
  [9,20],
  [15,7]
]
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void order(TreeNode* root, vector<vector<int>> & result, int leve){
        if(root == NULL)return;
        if(leve > result.size()) result.push_back(vector<int>());
        result[leve-1].push_back(root->val);
        order(root->left, result, leve+1);
        order(root->right, result, leve+1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        order(root, result, 1);
        return result;
    }
};

103. Binary Tree Zigzag Level Order Traversal(Medium)

  Given a binary tree, return the zigzag level order traversal of its nodes’ values. (ie, from left to right, then right to left for the next level and alternate between).

  • Example:
For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its zigzag level order traversal as:
[
  [3],
  [20,9],
  [15,7]
]
  • code:
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> result;
        queue<TreeNode*>    q;
        int                 level = 0;

        if (root != nullptr) {
            q.push(root);
        }
        while (!q.empty()) {
            vector<int> tmpResult;
            int n = q.size();
            for (int i = 0; i < n; i++) {
                auto curr = q.front();q.pop();
                tmpResult.push_back(curr->val);
                if (curr->left) {
                    q.push(curr->left);
                }
                if (curr->right) {
                    q.push(curr->right);
                }
            }
            if (level & 1) {
                reverse(tmpResult.begin(), tmpResult.end());
            }
            result.push_back(tmpResult);
            level++;
        }
        return result;
    }
};

104. Maximum Depth of Binary Tree(Easy)

  Given a binary tree, find its maximum depth.
  The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

  • Note: A leaf is a node with no children.

  • Example:

Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its depth = 3.
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {
        return root==NULL?0:1+ max(maxDepth(root->left),maxDepth(root->right));
    }
};

105. Construct Binary Tree from Preorder and Inorder Traversal(Medium)

  Given preorder and inorder traversal of a tree, construct the binary tree.

  • Note:
    You may assume that duplicates do not exist in the tree.

  • Example:

For example, given

preorder = [3,9,20,15,7]
inorder = [9,3,15,20,7]
Return the following binary tree:
    3
   / \
  9  20
    /  \
   15   7
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
/*
例如一个树,它的preorder是4 2 1 3 6 5 7    inorder是 1 2 3 4 5 6 7
很显然,preorder[0] 是root,而在inorder中,inorder[3] = 4 是中点;
然后就能从inorder中知道 0 <= index < 3的部分是root->left的 inorder; 4 <= index < inorder.size() 的部分是root->right的 inorder;
由此也能知道preorder中 1 <= index < 4 是root->left的reorder,4 <= index < preorder.size() 是root->right 的preorder; 
然后递归!
*/
class Solution {
public:
    TreeNode* tree(vector<int>& preorder, vector<int>& inorder,int b1,int e1,int b2,int e2){
        if(b1 > e1) return NULL;
        TreeNode* result = new TreeNode(preorder[b1]);
        if(b1 == e1) return result;
        int i = b2;
        while(inorder[i] != preorder[b1])i++;
        result->left = tree(preorder, inorder, b1+1, b1+i-b2, b2, i-1);
        result->right = tree(preorder, inorder, b1+i-b2+1, e1, i+1, e2);
        return result;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return tree(preorder, inorder, 0, preorder.size()-1,0,preorder.size()-1);
    }
};

106. Construct Binary Tree from Inorder and Postorder Traversal(Medium)

  Given inorder and postorder traversal of a tree, construct the binary tree.

  • Note:
    You may assume that duplicates do not exist in the tree.

  • Example:

For example, given

inorder = [9,3,15,20,7]
postorder = [9,15,7,20,3]
Return the following binary tree:
    3
   / \
  9  20
    /  \
   15   7
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution 
{
public:
    int findIndex(vector<int>& inorder,int start,int end, int value)
    {
        for(int i=start;i<=end;i++)
        {
            if(inorder[i]==value)
                return i;
        }
    }
    TreeNode* makeTree(vector<int>& postorder, vector<int>& inorder, int i,int j, int& p)
    {
        if(i > j)
            return NULL;
        TreeNode* node = new TreeNode(postorder[p]);
        p--;

        if(i==j)
            return node;

        int in = findIndex(inorder, i, j, node->val);
        node->right = makeTree(postorder, inorder,in+1, j, p);
        node->left = makeTree(postorder, inorder, i, in-1, p);
        return node;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) 
    {
        if(inorder.size() < 1 || postorder.size() < 1)
            return NULL;
        int p=postorder.size()-1;
        return makeTree(postorder, inorder, 0, p, p);
    }
};

107. Binary Tree Level Order Traversal II(Easy)

  Given a binary tree, return the bottom-up level order traversal of its nodes’ values. (ie, from left to right, level by level from leaf to root).

  • Example:
For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its bottom-up level order traversal as:
[
  [15,7],
  [9,20],
  [3]
]
  • code:
class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        vector<vector<int> > result;
        if(root == NULL)return result;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()){
            int size  = que.size();
            vector<int> level;
            for(int i =0; i< size;i++){
               TreeNode* cur = que.front();
               que.pop();
                level.push_back(cur->val);
                if(cur->left){
                    que.push(cur->left);
                }
                if(cur->right){
                    que.push(cur->right);
                }
            }
            result.push_back(level);

        }
        reverse(result.begin(),result.end());
        return result;
    }
};

108. Convert Sorted Array to Binary Search Tree(Easy)

  Given an array where elements are sorted in ascending order, convert it to a height balanced BST.
  For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

  • Example:
Given the sorted array: [-10,-3,0,5,9],
One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:

      0
     / \
   -3   9
   /   /
 -10  5
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode *sortedArrayToBSTDC(vector<int>& nums, int left, int right){
        if(left>=right){
            return NULL;
        }
        int mid = (left+right)/2;
        TreeNode *node = new TreeNode(nums[mid]);
        node->left = sortedArrayToBSTDC(nums, left, mid);
        node->right = sortedArrayToBSTDC(nums, mid + 1, right);
        return node;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return sortedArrayToBSTDC(nums, 0, nums.size());
    }
};

109. Convert Sorted List to Binary Search Tree(Medium)!!!

  Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
  For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

  • Example:
Given the sorted linked list: [-10,-3,0,5,9],

One possible answer is: [0,-3,9,-10,null,5], which represents the following height balanced BST:
      0
     / \
   -3   9
   /   /
 -10  5
  • code:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    TreeNode* sortedListToBST(ListNode* head) {
        int n = 0;
        ListNode* cur = head;
        while (cur) {
            ++n;
            cur = cur->next;
        }
        return convertSortedListToBSTHelper(&head, 0, n);
    }
private:
    TreeNode* convertSortedListToBSTHelper(ListNode** head, int s, int e) {
        if (s == e) return nullptr;
        int m = s + (e - s) / 2;
        TreeNode* left = convertSortedListToBSTHelper(head, s, m);
        TreeNode* curr = new TreeNode((*head)->val);
        *head = (*head)->next;  // 这里才得多揣摩
        auto right = convertSortedListToBSTHelper(head, m+1, e);
        curr->left = left;
        curr->right = right;
        return curr;
    }
};

110. Balanced Binary Tree

  Given a binary tree, determine if it is height-balanced.
  For this problem, a height-balanced binary tree is defined as:

a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

  • Example:
Given the following tree [3,9,20,null,null,15,7]:
    3
   / \
  9  20
    /  \
   15   7
Return true.

Given the following tree [1,2,2,3,3,null,null,4,4]:
       1
      / \
     2   2
    / \
   3   3
  / \
 4   4
Return false.
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool isBalancedHeight(TreeNode *node, int &height){
        if(node==NULL){
            height = 0;
            return true;
        }
        int hLeft, hRight;
        bool bLeft, bRight;
        bLeft = isBalancedHeight(node->left, hLeft);
        if(!bLeft){
            return false;
        }
        bRight = isBalancedHeight(node->right, hRight);
        if(!bRight){
            return false;
        }
        height = max(hLeft, hRight) + 1;
        return (hLeft + 1)>=hRight && (hRight + 1)>=hLeft;
    }
    bool isBalanced(TreeNode* root) {
        int height;
        return isBalancedHeight(root, height);
    }
};

111. Minimum Depth of Binary Tree(Easy)

  Given a binary tree, find its minimum depth.
  The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

  • Note: A leaf is a node with no children.

  • Example:

Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its minimum depth = 2.
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int minDepth(TreeNode *root) {
        if (root == NULL) return 0;
        if (root->left == NULL && root->right == NULL) return 1;

        if (root->left == NULL) return minDepth(root->right) + 1;
        else if (root->right == NULL) return minDepth(root->left) + 1;
        else return 1 + min(minDepth(root->left), minDepth(root->right));
    }

};

112. Path Sum(Easy)

  Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.

  • Note: A leaf is a node with no children.

  • Example:

Given the below binary tree and sum = 22,
      5
     / \
    4   8
   /   / \
  11  13  4
 /  \      \
7    2      1
return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if (!root) return false;
        if (!root->left && !root->right) return root->val == sum;
        bool res = false;
        if (root->left) {
            if (hasPathSum(root->left, sum - root->val)) return true;
        }
        if (root->right) {
            if (hasPathSum(root->right, sum - root->val)) return true;
        }
        return false;
    }
};

113. Path Sum II(Medium)

  Given a binary tree and a sum, find all root-to-leaf paths where each path’s sum equals the given sum.

  • Note: A leaf is a node with no children.

  • Example:

Given the below binary tree and sum = 22,
      5
     / \
    4   8
   /   / \
  11  13  4
 /  \    / \
7    2  5   1
Return:
[
   [5,4,11,2],
   [5,8,4,5]
]
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> res;

    void helper(TreeNode *root, int sum, vector<int> &path) {
        if (!root) return;
        if (!root->left && !root->right) {
            if (root->val != sum) return;
            path.push_back(sum);
            res.push_back(path);
            path.pop_back();
            return;
        }
        if (root->left) {
            path.push_back(root->val);
            helper(root->left, sum - root->val, path);
            path.pop_back();
        }
        if (root->right) {
            path.push_back(root->val);
            helper(root->right, sum - root->val, path);
            path.pop_back();
        }        
    }

    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<int> path;
        helper(root, sum, path);
        return res;
    }
};

114. Flatten Binary Tree to Linked List(Medium)

  Given a binary tree, flatten it to a linked list in-place.

  • Example:
For example, given the following tree:
    1
   / \
  2   5
 / \   \
3   4   6
The flattened tree should look like:
1
 \
  2
   \
    3
     \
      4
       \
        5
         \
          6
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    void flatten(TreeNode* root) {
        root = helper(root);
    }

    TreeNode* helper(TreeNode* root) {
        if (root == nullptr) {
            return nullptr;
        }

        TreeNode *origRight = root->right;
        root->right = helper(root->left);
        root->left = nullptr;

        TreeNode *p = root;

        while (p->right) {
            p = p->right;
        }

        p->right = helper(origRight);
        return root;
    }
};

115. Distinct Subsequences(Hard)

  Given a string S and a string T, count the number of distinct subsequences of S which equals T.
  A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, “ACE” is a subsequence of “ABCDE” while “AEC” is not).

  • Example:
Input: S = "rabbbit", T = "rabbit"
Output: 3
Explanation:

As shown below, there are 3 ways you can generate "rabbit" from S.
(The caret symbol ^ means the chosen letters)

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^

Input: S = "babgbag", T = "bag"
Output: 5
Explanation:

As shown below, there are 5 ways you can generate "bag" from S.
(The caret symbol ^ means the chosen letters)

babgbag
^^ ^
babgbag
^^    ^
babgbag
^    ^^
babgbag
  ^  ^^
babgbag
    ^^^
  • code:
class Solution {
public:
    int numDistinct(string s, string t) {
        if(s.length() < t.length()) return 0;
        int **result = new int*[s.length()+1];
        for(int i = 0; i < s.length()+1; i++) result[i] = new int[t.length()+1];
        result[0][0] = 1;
        for(int i = 1; i < s.length()+1; i++) result[i][0] = 1;               //这里需要注意下
        for(int i = 1; i < t.length()+1; i++) result[0][i] = 0;
        for(int i = 1; i < s.length()+1; i++){
            for(int j = 1; j < t.length()+1; j++){
                if(s[i-1] == t[j-1])
                    // result[i-1][j-1] 代表没加 s[i-1] 之前有多少满足子序列
                    // result[i-1][j] 代表之前有多少满足序列
                    result[i][j] = result[i-1][j-1] + result[i-1][j];
                else result[i][j] = result[i-1][j];      
            }
        }
        return result[s.length()][t.length()];
    }
};

116. Populating Next Right Pointers in Each Node(Medium)

  Given a binary tree

struct TreeLinkNode {
  TreeLinkNode *left;
  TreeLinkNode *right;
  TreeLinkNode *next;
}

  Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
  Initially, all next pointers are set to NULL.

  • Note:

    • You may only use constant extra space.
    • Recursive approach is fine, implicit stack space does not count as extra space for this problem.
    • You may assume that it is a perfect binary tree (ie, all leaves are at the same level, and every parent has two children).
  • Example:

Given the following perfect binary tree,
     1
   /  \
  2    3
 / \  / \
4  5  6  7
After calling your function, the tree should look like:
     1 -> NULL
   /  \
  2 -> 3 -> NULL
 / \  / \
4->5->6->7 -> NULL
  • code:
/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
    void connectRecurr(TreeLinkNode *root) {
        if (!root)
            return;

        if(root->left)
            root->left->next = root->right;
        if(root->right)
            root->right->next = root->next? root->next->left : NULL;
        connectRecurr(root->left);
        connectRecurr(root->right);
    }
public:
    void connect(TreeLinkNode *root) {
        if (!root)
            return;
        root->next = NULL;
        connectRecurr(root);
    }
};

117. Populating Next Right Pointers in Each Node II(Medium)

  Given a binary tree

struct TreeLinkNode {
  TreeLinkNode *left;
  TreeLinkNode *right;
  TreeLinkNode *next;
}

  Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
  Initially, all next pointers are set to NULL.

  • Note:

    • You may only use constant extra space.
    • Recursive approach is fine, implicit stack space does not count as extra space for this problem.
  • Example:

Given the following binary tree,
     1
   /  \
  2    3
 / \    \
4   5    7
After calling your function, the tree should look like:
     1 -> NULL
   /  \
  2 -> 3 -> NULL
 / \    \
4-> 5 -> 7 -> NULL
  • code:
/**
 * Definition for binary tree with next pointer.
 * struct TreeLinkNode {
 *  int val;
 *  TreeLinkNode *left, *right, *next;
 *  TreeLinkNode(int x) : val(x), left(NULL), right(NULL), next(NULL) {}
 * };
 */
class Solution {
public:
    void connect(TreeLinkNode *root) {
//Non-recurvise solution:
        if(root==NULL) return;
        TreeLinkNode* childHead=NULL; //指向下一层的第一个节点
        TreeLinkNode* child=NULL;
        while(root!=NULL){ //从上到下的while循环
            while(root!=NULL){ //从左到右的while循环
                if(root->left!=NULL){
                    if(childHead!=NULL){
                        child->next=root->left;
                        child=root->left;
                    }else{
                        childHead=root->left;
                        child=root->left;
                    }
                }

                if(root->right!=NULL){
                    if(childHead!=NULL){
                        child->next=root->right;
                        child=root->right;
                    }else{
                        childHead=root->right;
                        child=root->right;
                    }
                }
                root=root->next;
            }
            root=childHead;
            child=NULL;
            childHead=NULL;
        }
    }
};

118. Pascal’s Triangle(Easy)

  Given a non-negative integer numRows, generate the first numRows of Pascal’s triangle.

LeetCode8

  In Pascal’s triangle, each number is the sum of the two numbers directly above it.

  • Example:
Input: 5
Output:
[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]
  • code:
class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> res;
        if(numRows==0)
            return res;
        res.push_back(vector<int>{1});
        for(int i=1; i<numRows; i++)
        {
            vector<int> row;
            for(int j=0; j<i+1; j++)
            {
                if(j==0||j==i)
                    row.push_back(1);
                else
                    row.push_back(res[i-1][j]+res[i-1][j-1]);
            }
            res.push_back(row);
        }
        return res;
    }
};

119. Pascal’s Triangle II(Easy)

  Given a non-negative index k where k ≤ 33, return the k t h index row of the Pascal’s triangle.
  Note that the row index starts from 0.

LeetCode8

  In Pascal’s triangle, each number is the sum of the two numbers directly above it.

  • Example:
Input: 3
Output: [1,3,3,1]
  • code:
class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> res;        
        vector<int> newTemp;
        newTemp.push_back(1);
        if(rowIndex==0)
            return newTemp;
        newTemp.push_back(1);
        if(rowIndex==1)
            return newTemp;
        for(int i=2;i<=rowIndex;i++){
            res={};
            res.push_back(1);
            for(int j=0;j<newTemp.size()-1;j++)
                res.push_back(newTemp[j]+newTemp[j+1]);
            res.push_back(1);
            newTemp=res;            
        }
        return res;
    }
};

120. Triangle(Medium)

  Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
  For example, given the following triangle

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]

  The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).

  • Note:
    Bonus point if you are able to do this using only O(n) extra space, where n is the total number of rows in the triangle.

  • code:

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int i, j, m = triangle.size();
        vector<int> dp(triangle[m - 1].size());
        dp[0] = triangle[0][0];
        for(i = 1; i < m; i++) {
            for(j = triangle[i].size() - 1; j >= 0 ; j--) {
                if(j == 0) {
                    dp[j] = dp[j] + triangle[i][j];
                }
                else if(j == triangle[i].size() - 1) {
                    dp[j] = dp[j - 1] + triangle[i][j];
                }
                else {
                    dp[j] = min(dp[j - 1], dp[j]) + triangle[i][j];
                }
                //cout << dp[j] << " ";
            }
            //cout << endl;
        }
        int res = dp[0];
        for(i = 1; i < m; i++) {
            res = min(res, dp[i]);
        }
        return res;
    }
};

121. Best Time to Buy and Sell Stock(Easy)

  Say you have an array for which the i t h element is the price of a given stock on day i.
  If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
  Note that you cannot sell a stock before you buy one.

  • Example:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
             Not 7-1 = 6, as selling price needs to be larger than buying price.

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
  • code:
class Solution { //一定要考虑传统方法的哪里是重复计算或者多余计算然后想办法把重复或者多余计算给排除
public: //上面的方法中,后面有比前面小的数字,当没有确定出卖出日期的时候,便不需要再计算后面数字了
    int maxProfit(vector<int>& prices) { //即使暂时计算出卖出日期,后面有更大的利益,也可以把日期对换
        if(prices.size()<=1) return 0; //看 122. Best Time to Buy and Sell Stock II
        int result = 0;
        for(int i = 0; i < prices.size()-1; i++)
            for(int j = i + 1; j < prices.size(); j++){
                if(prices[j] <= prices[i]){
                    i = j;
                }else{
                    result = max(prices[j] - prices[i],result);
                }
            }
        return result;
    }
};

122. Best Time to Buy and Sell Stock II(Easy)

  Say you have an array for which the i t h element is the price of a given stock on day i.
  Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times).

  • Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

  • Example:

Input: [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
             Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
  • code:
class Solution { //一定要考虑传统方法的哪里是重复计算或者多余计算然后想办法把重复或者多余计算给排除
public: //上面的方法中,后面有比前面小的数字,当没有确定出卖出日期的时候,便不需要再计算后面数字了
    int maxProfit(vector<int>& prices) { //即使暂时计算出卖出日期,后面有更大的利益,也可以把日期对换
        if(prices.size()<=1) return 0;
        int result = 0;
        for(int i = 0; i < prices.size()-1; i++)
            for(int j = i + 1; j < prices.size(); j++){
                if(prices[j] <= prices[i]){
                    i = j;
                }else{
                    result += (prices[j] - prices[i]);
                    i = j;  //仅添加了这一行
                }
            }
        return result;
    }
};

123. Best Time to Buy and Sell Stock III(Hard)

  Say you have an array for which the i t h element is the price of a given stock on day i.
  Design an algorithm to find the maximum profit. You may complete at most two transactions.

  • Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

  • Example:

Input: [3,3,5,0,0,3,1,4]
Output: 6
Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
             Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3.

Input: [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
             Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are
             engaging multiple transactions at the same time. You must sell before buying again.

Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.
  • code:
class Solution {
public:
    int maxProfit(vector<int>& prices) {  //这个太经典了,必须列出来1 2 4 2 5 7 0 4 9 0
        int firstBuy = INT_MIN, firstSell = 0; // 第二次买进卖出是根据第一次的利润为基础的,太经典了
        int secondBuy = INT_MIN, secondSell = 0;
        for (int curPrice : prices) {
            firstBuy = max(firstBuy, -curPrice); // The max profit after you buy first stock
            firstSell = max(firstSell, firstBuy + curPrice); // The max profit after you sell it
            secondBuy = max(secondBuy, firstSell - curPrice); // The max profit after you buy the second stock
            secondSell = max(secondSell, secondBuy + curPrice); // The max profit after you sell the second stock
        }
        return secondSell; // secondSell will be the max profit after passing the prices
    }
};

124. Binary Tree Maximum Path Sum(Hard)

  Given a non-empty binary tree, find the maximum path sum.
  For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child
  connections. The path must contain at least one node and does not need to go through the root.

  • Example:
Input: [1,2,3]
       1
      / \
     2   3
Output: 6

Input: [-10,9,20,null,null,15,7]
   -10
   / \
  9  20
    /  \
   15   7
Output: 42
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int maxPathSum(TreeNode* root) {
    if (root == nullptr) return 0;
    ret_ = root->val;
    mySolve(root);
    return ret_;
    }

    int mySolve(TreeNode* root) {
        if (root == nullptr) return 0;
        auto left = mySolve(root->left);
        auto right = mySolve(root->right);
        ret_ = max(ret_, left + root->val + right);
        return max(0, max(left + root->val, right + root->val));
    }
    int ret_;
};

125. Valid Palindrome(Easy)

  Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

  • Note: For the purpose of this problem, we define empty string as valid palindrome.

  • Example:

Input: "A man, a plan, a canal: Panama"
Output: true

Input: "race a car"
Output: false
  • code:
class Solution {
public:
    bool isAlphanumeric(char c)
    {
        return isAlphabetic(c) || isNumeric(c);
    }
    bool isAlphabetic(char c)
    {
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    }
    bool isNumeric(char c)
    {
        return (c >= '0' && c <= '9');
    }
    bool isPalindrome(string s) 
    {
        int n = s.size();
        if( n < 2)
            return true;
        int left = 0, right = n-1;

        while(left < right)
        {
            while(left < right && isAlphanumeric(s[left]) == false)
                left++;
            while(left < right && isAlphanumeric(s[right]) == false)
                right--;

            if(left < right)
            {
                if(isNumeric(s[left]) && (s[left] != s[right]))
                    return false;
                if(isAlphabetic(s[left]) && (toupper(s[left]) != toupper(s[right])))
                    return false;
                left++;
                right--;
            }
        }
        return true;
    }
};

126. Word Ladder II(Hard)

  Given two words (beginWord and endWord), and a dictionary’s word list, find all shortest transformation sequence(s) from beginWord to endWord, such that:
  1. Only one letter can be changed at a time
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

  • Note:

    • Return an empty list if there is no such transformation sequence.
    • All words have the same length.
    • All words contain only lowercase alphabetic characters.
    • You may assume no duplicates in the word list.
    • You may assume beginWord and endWord are non-empty and are not the same.
  • Example:

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

Output:
[
  ["hit","hot","dot","dog","cog"],
  ["hit","hot","lot","log","cog"]
]

Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

Output: []

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
  • code:
class Solution {                          //36ms
public:
    vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string> wordHash;
        for (int i=0;i<wordList.size();i++){
            wordHash.insert(wordList[i]);
        }
        std::vector<std::vector<std::string> > paths;
        if (!wordHash.count(endWord))
            return paths;
        std::vector<std::string> path(1, beginWord);
        if (beginWord == endWord) {
            paths.push_back(path);
            return paths;
        }
        std::unordered_set<std::string> words1, words2;
        words1.insert(beginWord);
        words2.insert(endWord);
        std::unordered_map<std::string, std::vector<std::string> > nexts;
        bool words1IsBegin = false;
        if (findLaddersHelper(words1, words2, wordHash, nexts, words1IsBegin))
            getPath(beginWord, endWord, nexts, path, paths);
        return paths;
    }
private:
    bool findLaddersHelper(
        std::unordered_set<std::string> &words1,
        std::unordered_set<std::string> &words2,
        std::unordered_set<std::string> &dict,
        std::unordered_map<std::string, std::vector<std::string> > &nexts,
        bool &words1IsBegin) {
        words1IsBegin = !words1IsBegin;
        if (words1.empty())
            return false;
        if (words1.size() > words2.size())
            return findLaddersHelper(words2, words1, dict, nexts, words1IsBegin);
        for (auto it = words1.begin(); it != words1.end(); ++it)
            dict.erase(*it);
        for (auto it = words2.begin(); it != words2.end(); ++it)
            dict.erase(*it);
        std::unordered_set<std::string> words3;
        bool reach = false;
        for (auto it = words1.begin(); it != words1.end(); ++it) {
            std::string word = *it;
            for (auto ch = word.begin(); ch != word.end(); ++ch) {
                char tmp = *ch;
                for (*ch = 'a'; *ch <= 'z'; ++(*ch))
                    if (*ch != tmp)
                        if (words2.find(word) != words2.end()) {
                            reach = true;
                            words1IsBegin ? nexts[*it].push_back(word) : nexts[word].push_back(*it);
                        }
                        else if (!reach && dict.find(word) != dict.end()) {
                            words3.insert(word);
                            words1IsBegin ? nexts[*it].push_back(word) : nexts[word].push_back(*it);
                        }
                *ch = tmp;
            }
        }
        return reach || findLaddersHelper(words2, words3, dict, nexts, words1IsBegin);
    }
    void getPath(
        std::string beginWord,
        std::string endWord,
        std::unordered_map<std::string, std::vector<std::string> > &nexts,
        std::vector<std::string> &path,
        std::vector<std::vector<std::string> > &paths) {
        if (beginWord == endWord)
            paths.push_back(path);
        else
            for (auto it = nexts[beginWord].begin(); it != nexts[beginWord].end(); ++it) {
                path.push_back(*it);
                getPath(*it, endWord, nexts, path, paths);
                path.pop_back();
            }
    }
};

127. Word Ladder(Medium)

  Given two words (beginWord and endWord), and a dictionary’s word list, find the length of shortest transformation sequence from beginWord to endWord, such that:
  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

  • Note:

    • Return 0 if there is no such transformation sequence.
    • All words have the same length.
    • All words contain only lowercase alphabetic characters.
    • You may assume no duplicates in the word list.
    • You may assume beginWord and endWord are non-empty and are not the same.
  • Example:

Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]

Output: 5
Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]

Output: 0

Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
  • code:
class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        unordered_set<string> fwd, bwd, dict(wordList.begin(), wordList.end());
        if (dict.find(endWord) == dict.end()) 
            return 0;
        fwd.insert(beginWord), bwd.insert(endWord), dict.erase(beginWord);

        int len = 1;
        while (!fwd.empty()) {
            if (fwd.size() > bwd.size()) {
                swap(fwd, bwd);
            }
            unordered_set<string> next;
            for (auto &word:fwd) {
                string str = word;
                for (int i = 0; i < str.size(); ++i) {
                    for (char ch = 'a'; ch <= 'z'; ++ch) {
                        if (ch == word[i]) {
                            continue;
                        }
                        str[i] = ch;
                        if (bwd.find(str) != bwd.end()) {
                            return len+1;
                        }
                        if (dict.find(str) != dict.end()) {
                            next.insert(str), dict.erase(str);
                        }
                        str[i] = word[i];
                    }
                }
            }
            fwd = move(next), ++len;
        }
        return 0;
    }
};

128. Longest Consecutive Sequence(Hard)

  Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
  Your algorithm should run in O(n) complexity.

  • Example:
Input: [100, 4, 200, 1, 3, 2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.
  • code:
class Solution { // 还有特么直接用排序的
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_set<int> numsSet(nums.begin(), nums.end());
        int longest = 0;

        for (int num : nums) {
            if (!numsSet.count(num - 1)) {
                int currentNumber = num;
                while (numsSet.count(currentNumber)) {
                    currentNumber++;
                }
                longest = max(longest, currentNumber - num);
            }
        }
        return longest;
    }
};

129. Sum Root to Leaf Numbers(Medium)

  Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.
  An example is the root-to-leaf path 1->2->3 which represents the number 123.
  Find the total sum of all root-to-leaf numbers.

  • Note: A leaf is a node with no children.

  • Example:

Input: [1,2,3]
    1
   / \
  2   3
Output: 25
Explanation:
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.
Therefore, sum = 12 + 13 = 25.

Input: [4,9,0,5,1]
    4
   / \
  9   0
 / \
5   1
Output: 1026
Explanation:
The root-to-leaf path 4->9->5 represents the number 495.
The root-to-leaf path 4->9->1 represents the number 491.
The root-to-leaf path 4->0 represents the number 40.
Therefore, sum = 495 + 491 + 40 = 1026.
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int sumNumbers(TreeNode* root) {
        if(root == NULL)
            return 0;
        int sum = 0;
        string s;
        sumNumbers(root, s, sum);
        return sum;
    }
    void sumNumbers(TreeNode* node, string s, int &sum)
    {
        if(node == NULL)
        {
            sum += stoi(s);
            return;
        }
        s.append(1, '0'+ node->val);
        if(!node->left)
            sumNumbers(node->right, s, sum);
        else if(!node->right)
            sumNumbers(node->left, s, sum);
        else
        {
            sumNumbers(node->left, s, sum);
            sumNumbers(node->right, s, sum);
        }
    }
};

130. Surrounded Regions(Medium)

  Given a 2D board containing ‘X’ and ‘O’ (the letter O), capture all regions surrounded by ‘X’.
  A region is captured by flipping all ‘O’s into ‘X’s in that surrounded region.

  • Example:
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:
X X X X
X X X X
X X X X
X O X X
  • Explanation:
    Surrounded regions shouldn’t be on the border, which means that any ‘O’ on the border of the board are not flipped to ‘X’. Any ‘O’ that is not on the border and it is not connected to an ‘O’ on the border will be flipped to ‘X’. Two cells are connected if they are adjacent cells connected horizontally or vertically.

  • code:

class Solution {
public:
    bool checkEdge(pair<int, int> pos, int w, int h){
        if(pos.first >= 0 && pos.first < h && pos.second >= 0 && pos.second < w)
            return true;
        return false;
    }
    void BFS(vector<vector<char>>& board, int i, int j){
        queue<pair<int, int>> q;
        q.push(make_pair(i, j));
        board[i][j] = 'S';
        int h = board.size(), w = board[0].size();
        while(!q.empty()){
            pair<int, int> p = q.front();
            q.pop();
            pair<int, int> dir[4] = {{p.first - 1, p.second},
                                   {p.first + 1, p.second},
                                  {p.first, p.second - 1},
                                  {p.first, p.second + 1}};
            for(int i = 0; i < 4; i++)
                if(checkEdge(dir[i], w, h)){
                    if(board[dir[i].first][dir[i].second] == 'O'){
                        q.push(make_pair(dir[i].first, dir[i].second));
                        board[dir[i].first][dir[i].second] = 'S';
                    }   
                }
        }
    }
    void solve(vector<vector<char>>& board) {
        int h = board.size(); 
        if(h == 0) return;
        int w = board[0].size();
        for(int i = 0; i < h; i++){
            if(board[i][0] == 'O')
                BFS(board, i, 0);
            if(board[i][w - 1] == 'O')
                BFS(board, i, w - 1);
        }

        for(int i = 0; i < w; i++){
            if(board[0][i] == 'O')
                BFS(board, 0, i);
            if(board[h - 1][i] == 'O')
                BFS(board, h - 1, i);
        }
        for(int i = 0; i < h; i++)
            for(int j = 0; j < w; j++){
                if(board[i][j] == 'S')
                    board[i][j] = 'O';
                else
                    board[i][j] = 'X';
            }
    }
};

131. Palindrome Partitioning(Medium)

  Given a string s, partition s such that every substring of the partition is a palindrome.
  Return all possible palindrome partitioning of s.

  • Example:
Input: "aab"
Output:
[
  ["aa","b"],
  ["a","a","b"]
]
  • code:
class Solution {
private:
    vector<vector<bool> > palindrom;
public:
    void generatePartitions(const string& s, int pos, vector<string>& partition, vector<vector<string> >& res) {
        if (pos >= s.size()) {
            res.push_back(partition);
            return;
        }

        for (int i = pos; i < s.size(); ++i) {
            if (palindrom[pos][i]) {
                partition.push_back(s.substr(pos, i - pos + 1));
                generatePartitions(s, i + 1, partition, res);
                partition.pop_back();
            }
        }
    }

    vector<vector<string>> partition(string s) {
        vector<vector<string> > res;
        vector<string> partition;

        if (s.empty()) {
            return res;
        }

        palindrom.resize(s.size());
        for (int i = 0; i < s.size(); ++i) {
            palindrom[i].resize(s.size());
        }

        for (int i = s.size() - 1; i >= 0; --i) {
            for (int j = i; j < s.size(); ++j) {
                if (s[i] == s[j] && (j - i <= 1 || palindrom[i + 1][j - 1])) {
                    palindrom[i][j] = true;
                }
            }
        }

        generatePartitions(s, 0, partition, res);
        return res;
    }
};

132. Palindrome Partitioning II(Hard)

  Given a string s, partition s such that every substring of the partition is a palindrome.
  Return the minimum cuts needed for a palindrome partitioning of s.

  • Example:
Input: "aab"
Output: 1
Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut.
  • code:
class Solution {     // 动态规划贪心算法!!厉害
public:
    int minCut(string s) {
        int n = s.size();
        vector<int> cut(n+1, 0);  // number of cuts for the first k characters
        for (int i = 0; i <= n; i++) cut[i] = i-1;
        for (int i = 0; i < n; i++) {
            for (int j = 0; i-j >= 0 && i+j < n && s[i-j]==s[i+j] ; j++) // odd length palindrome
                cut[i+j+1] = min(cut[i+j+1],1+cut[i-j]);

            for (int j = 1; i-j+1 >= 0 && i+j < n && s[i-j+1] == s[i+j]; j++) // even length palindrome
                cut[i+j+1] = min(cut[i+j+1],1+cut[i-j+1]);
        }
        return cut[n];
    }
};

133. Clone Graph(Medium)

  Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors.
  OJ’s undirected graph serialization:
  Nodes are labeled uniquely.
  We use # as a separator for each node, and , as a separator for node label and each neighbor of the node.
  As an example, consider the serialized graph {0,1,2#1,2#2,2}.
  The graph has a total of three nodes, and therefore contains three parts as separated by #.
  1. First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
  2. Second node is labeled as 1. Connect node 1 to node 2.
  3. Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle.
  Visually, the graph looks like the following:

       1
      / \
     /   \
    0 --- 2
         / \
         \_/
  • code:
/**
 * Definition for undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    UndirectedGraphNode* cloneGraph(UndirectedGraphNode* node) {
        if ( node == NULL ) return NULL;

        unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> ucg_map;
        UndirectedGraphNode* res= ucg_map[node] = new UndirectedGraphNode(node->label);
        queue<UndirectedGraphNode*> processed;
        processed.push(node);
        while ( not processed.empty() )
        {
            UndirectedGraphNode* t= processed.front();
            processed.pop();
            for (auto &x:t->neighbors)
            {
                if ( ucg_map.find(x) == ucg_map.end() )
                {
                    ucg_map[x] = new UndirectedGraphNode(x->label);
                    processed.push(x);
                }
                ucg_map[t]->neighbors.push_back(ucg_map[x]);
            }
        }
        return res;
    }
};

134. Gas Station(Medium)

  There are N gas stations along a circular route, where the amount of gas at station i is gas[i].
  You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.
  Return the starting gas station’s index if you can travel around the circuit once in the clockwise direction, otherwise return -1.

  • Note:

    • If there exists a solution, it is guaranteed to be unique.
    • Both input arrays are non-empty and have the same length.
    • Each element in the input arrays is a non-negative integer.
  • Example:

Input: 
gas  = [1,2,3,4,5]
cost = [3,4,5,1,2]

Output: 3

Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.

Input: 
gas  = [2,3,4]
cost = [3,4,3]

Output: -1

Explanation:
You can't start at station 0 or 1, as there is not enough gas to travel to the next station.
Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
Therefore, you can't travel around the circuit once no matter where you start.
  • code:
class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int l=gas.size();
        int i=0;
        while(i<l)
        {
            int j=i;
            int petrol = gas[i];
            while((i+1)%l != j && cost[i%l]<=petrol)
            {
                petrol -= cost[i%l];
                i++;
                petrol += gas[i%l];

            }
            // cout<<petrol<<i<<j<<endl;
            if((i+1)%l == j && cost[i%l] <= petrol)
                return j;
            i++;
        }
        return -1;
    }
};

135. Candy(hard)

  There are N children standing in a line. Each child is assigned a rating value.
  You are giving candies to these children subjected to the following requirements:

  • Each child must have at least one candy.
  • Children with a higher rating get more candies than their neighbors.

  What is the minimum candies you must give?

  • Example:
Input: [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.

Input: [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
             The third child gets 1 candy because it satisfies the above two conditions.
  • code:
class Solution {
public:
    int candy(vector<int>& ratings) {
        int n = ratings.size();
        vector<int> candies(n, 1);
        for (int i = 1; i < n; i++) {
            if (ratings[i] > ratings[i-1]) {
                candies[i] = candies[i-1] + 1;
            }
        }
        for (int i = n-2; i >= 0; i--) {
            if (ratings[i] > ratings[i+1]) {
                candies[i] = max(candies[i], candies[i+1] + 1);
            }
        }
        return accumulate(candies.begin(), candies.end(), 0);
    }
};

136. Single Number(Easy)

  Given a non-empty array of integers, every element appears twice except for one. Find that single one.

  • Note:
    Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

  • Example:

Input: [2,2,1]
Output: 1

Input: [4,1,2,1,2]
Output: 4
  • code:
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int r = nums[0];
        for (int i = 1; i < nums.size(); i++) {
            r ^= nums[i];
        }
        return r;
    }
};

137. Single Number II(Medium)

  Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.

  • Note:
    Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

  • Example:

Input: [2,2,3,2]
Output: 3

Input: [0,1,0,1,0,1,99]
Output: 99
  • code:
class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int var[32]={0};
        for(int i=0;i<32;i++){
            for(auto num:nums){
                var[i]+=(num>>i)&1;

            }
            var[i]%=3;
        }
        int res=0;
        for(int i=0;i<32;i++){
            res+=var[i]<<i;
        }
        return res;
    }
};

138. Copy List with Random Pointer(Medium)

  A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
  Return a deep copy of the list.

  • code:
/**
 * Definition for singly-linked list with a random pointer.
 * struct RandomListNode {
 *     int label;
 *     RandomListNode *next, *random;
 *     RandomListNode(int x) : label(x), next(NULL), random(NULL) {}
 * };
 */
class Solution {
public:
    RandomListNode *copyRandomList(RandomListNode *head) {

    if(head == nullptr)
        return nullptr;

    // Pass 1: Created copy node immediately after the original node.
    auto cur = head;
    while (cur)
    {
        auto next = cur->next;
        auto newNode = new RandomListNode(cur->label);
        cur->next = newNode;
        newNode->next = next;
        cur = next;
    }

    // Pass 2: Assign random pointers.
    cur = head;
    while (cur)
    {
        cur->next->random = cur->random? cur->random->next: nullptr ;
        cur = cur->next->next;
    }

    // Pass 3: Separate original linkedlist and copy linkedlist.
    cur = head;
    auto copyhead = head->next;
    while (cur)
    {
        auto next = cur->next->next;
        cur->next->next = next? next->next: nullptr;
        cur->next = next;
        cur = next;
    }

    return copyhead;
    }
};

139. Word Break(Medium)

  Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

  • Note:

    • The same word in the dictionary may be reused multiple times in the segmentation.
    • You may assume the dictionary does not contain duplicate words.
  • Example:

Input: s = "leetcode", wordDict = ["leet", "code"]
Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".

Input: s = "applepenapple", wordDict = ["apple", "pen"]
Output: true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
             Note that you are allowed to reuse a dictionary word.

Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
Output: false
  • code:
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        int ll = s.size();
        int dict = wordDict.size();
        vector<bool> dp(ll+1,false);
        dp[0] = true;
        for(int i ;i < ll+1 ; i++){
            for(int j = 0;j<dict;j++){
                if(dp[i]){
                    string str = s.substr(i,wordDict[j].size());
                    if(str == wordDict[j]){
                        dp[i+wordDict[j].size()] = true;
                    }
                }
            }
        }
        return dp[ll];
    }
};

140. Word Break II(Hard)

  Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences.

  • Note:

    • The same word in the dictionary may be reused multiple times in the segmentation.
    • You may assume the dictionary does not contain duplicate words.
  • Example:

Input:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
Output:
[
  "cats and dog",
  "cat sand dog"
]

Input:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
Output:
[
  "pine apple pen apple",
  "pineapple pen apple",
  "pine applepen apple"
]
Explanation: Note that you are allowed to reuse a dictionary word.

Input:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
Output:
[]
  • code:
class Solution {

public:
    // time: O(n^2), space: O(n^2)
    vector<string> wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> dict(wordDict.begin(), wordDict.end());
        unordered_map<string, vector<string>> map;
        return wordBreak(s, dict, map);
    }

private:
    vector<string> wordBreak(string s, unordered_set<string>& dict, unordered_map<string, vector<string>>& map) {
        if (map.count(s))
            return map[s];

        vector<string> result;
        if (dict.count(s)) {
            result.push_back(s);
        }

        for(int i = 1; i < s.size(); i ++ ) {
            string str = s.substr(i);
            if (dict.count(str)) {
                vector<string> temp = wordBreak(s.substr(0, i), dict, map);
                if (!temp.empty()) {
                    for(auto prev : temp) {
                        result.push_back(prev + " " + str);
                    }
                }
            }
        }

        map[s] = result;
        return result;

    }
};

141. Linked List Cycle(Easy)

  Given a linked list, determine if it has a cycle in it.
  Follow up:
  Can you solve it without using extra space?

  • code:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast && slow) {
            slow = slow->next;
            fast = fast->next;
            if (fast)
                fast = fast->next;
            if (fast == slow && slow != nullptr)
                return true;
        }
        return false;
    }
};

142. Linked List Cycle II(Medium)

  Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Note: Do not modify the linked list.
  Follow up:
  Can you solve it without using extra space?

  • code:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(!head) return NULL;
        if(head -> next == NULL) return NULL;
        ListNode *fast = head -> next -> next, *slow = head -> next;
        while(fast != slow){
            if(fast == NULL || fast -> next == NULL || fast -> next -> next == NULL) return NULL;
            fast = fast -> next -> next;
            if(slow == NULL) return NULL;
            slow = slow -> next;
        }


        fast = head;
        while(fast != slow){
            fast = fast -> next;
            slow = slow -> next;
        }

        return fast;
    }
};

143. Reorder List(Medium)

  Given a singly linked list L : L 0 L 1 L n 1 L n ,
  reorder it to: L 0 L n L 1 L n 1 L 2 L n 2

  • Example:
Given 1->2->3->4, reorder it to 1->4->2->3.

Given 1->2->3->4->5, reorder it to 1->5->2->4->3.
  • code:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void reorderList(ListNode *head) {
        if(head == NULL || head->next == NULL || head->next->next==NULL)
            return;
        //find the middle of the list, and split into two lists.    
        ListNode *p=head,*q=head;
        while(p && q && q->next && q->next->next){
            p=p->next;
            q=q->next->next;
        }

        ListNode *mid = p->next;
        p->next=NULL;
        p=head;
        //reverse from the middle to the end
        ListNode *q1=mid, *q2,*q3;
        if(mid->next){
            q1=mid;
            q2=mid->next;
            while(q2){
                q3=q2->next;
                q2->next=q1;
                q1=q2;
                q2=q3;

            }
            mid->next=NULL;
        }
        q=q1;
        //merge these two list
        ListNode *s=p;
        p=p->next;
        while(p && q){
           s->next=q;
           s=s->next;
           q=q->next;

           s->next=p;
           s=s->next;
           p=p->next;
        }
        if(p){
            s->next=p;
        }
        if(q){
            s->next=q;
        }
    }
};

144. Binary Tree Preorder Traversal(Medium)

  Given a binary tree, return the preorder traversal of its nodes’ values.

  • Example:
Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [1,2,3]
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        std::stack<TreeNode*> temp;
        while (root || !temp.empty()) {
            while (root) {
                temp.push(root);
                res.push_back(root->val);
                root = root->left;
            }
            root = temp.top();
            temp.pop();
            root = root->right;
        }
        return res;
    }
};

145. Binary Tree Postorder Traversal(Hard)

  Given a binary tree, return the postorder traversal of its nodes’ values.

  • Example:
Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [3,2,1]
  • code:
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> nodes;
        stack<TreeNode*> todo;
        TreeNode* cur = root;
        TreeNode* last = NULL;
        while (cur || !todo.empty()) {
            if (cur) {
                todo.push(cur);
                cur = cur->left;
            } 
            else {
                TreeNode* top = todo.top();
                if (top->right && (last!=top->right)) {
                    cur = top->right;
                } 
                else {
                    nodes.push_back(top->val);
                    last = top;
                    todo.pop();
                }
            }
        }
        return nodes;
    }
};

146. LRU Cache(Hard)

  Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put.
  get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
  put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

  Follow up:
  Could you do both operations in O(1) time complexity?

  • Example:
LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1);       // returns 1
cache.put(3, 3);    // evicts key 2
cache.get(2);       // returns -1 (not found)
cache.put(4, 4);    // evicts key 1
cache.get(1);       // returns -1 (not found)
cache.get(3);       // returns 3
cache.get(4);       // returns 4
  • code:
#include <unordered_map>
#include <memory>
struct Node {
    Node(int key, int value): key(key), val(value), next(NULL), prev(NULL) {};

    int key;
    int val;
    Node* next;
    Node* prev;
};

struct LinkedList {

    LinkedList():
    n(0),
    head(new Node(0, 0)),
    tail(new Node(0, 0)) {
        head->next = tail;
        tail->prev = head;
    }

    void AddToTop(Node* node) {
        Node* after_head = head->next;
        head->next = node;
        node->prev = head;
        node->next = after_head;
        after_head->prev = node;
        n += 1;
    }

    void RemoveNode(Node* node) {
        // without delelte
        Node* before_node = node->prev;
        Node* after_node = node->next;
        before_node->next = after_node;
        after_node->prev = before_node;
        n -= 1;
    }

    void MoveToTop(Node* node) {
        RemoveNode(node);
        AddToTop(node);
    }

    int n;
    Node*  head;
    Node*  tail;
};


class LRUCache {
private:
    unordered_map<int, Node*> map_;
    int capacity_;
    LinkedList list_;

public:
    LRUCache(int capacity) : capacity_(capacity) {
    }

    int get(int key) {
        if (map_.find(key) == map_.end())
            return -1;

        Node* node = map_[key];
        list_.MoveToTop(node);
        return node->val;
    }

    void put(int key, int value) {
        if (map_.find(key) == map_.end()) {
            Node* node = new Node(key, value);
            list_.AddToTop(node);
            map_[key] = node;

            if (list_.n > capacity_) {
                Node* last_node = list_.tail->prev;
                list_.RemoveNode(last_node);
                map_.erase(last_node->key);
                delete last_node;
            }

        } else {
            Node* node = map_[key];
            node->val = value;
            list_.MoveToTop(node);

        }
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

147. Insertion Sort List(Medium)

  Sort a linked list using insertion sort.

LeetCode9

  A graphical example of insertion sort. The partial sorted list (black) initially contains only the first element in the list.
  With each iteration one element (red) is removed from the input data and inserted in-place into the sorted list

  • Algorithm of Insertion Sort:

    • Insertion sort iterates, consuming one input element each repetition, and growing a sorted output list.
    • At each iteration, insertion sort removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there.
    • It repeats until no input elements remain.
  • Example:

Input: 4->2->1->3
Output: 1->2->3->4

Input: -1->5->3->4->0
Output: -1->0->3->4->5
  • code:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void ins(ListNode* head, ListNode* node){
        while(node->val > head->next->val) head = head->next;
        node->next = head->next;
        head->next = node;
    }
    ListNode* insertionSortList(ListNode* head) {
        ListNode *result = new ListNode(INT_MIN);
        ListNode *buf;
        result->next = head;
        if(head == NULL) return NULL;
        while(head->next != NULL){
            if(head->next->val < head->val) {
                buf = head->next;
                head->next = head->next->next;
                ins(result,buf);
            }else head = head->next;
        }
        return result->next;
    }
};

148. Sort List(Medium)

  Sort a linked list in O(n log n) time using constant space complexity.

  • Example:
Input: 4->2->1->3
Output: 1->2->3->4

Input: -1->5->3->4->0
Output: -1->0->3->4->5
  • code:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}             老衲自己写的,91%,我骄傲!  
 * };
 */
class Solution {
public:
    ListNode* sort(ListNode* head,int a){                    //给定需要排序的列表,里面有a个元素
        int middle = a/2;                       
        int m = middle;
        if(a == 1){ head->next = NULL; return head;}          //长度为1和2的情况,特殊的是确保尾部必须指向空,因为后面要合并  
        if(a == 2){
            if(head->val > head->next->val){
                int buf;
                buf = head->val;
                head->val = head->next->val;
                head->next->val = buf;
            }
            head->next->next = NULL;
            return head;
        }
        ListNode* buf = head;
        while(m > 1){ buf = buf->next; m--;}                 //找到中间的值的上面那个
        ListNode* right = sort(buf->next,a-middle);
        buf->next = NULL;                                    //因为需要把它后面也给弄空
        ListNode* left = sort(head,middle);
        ListNode* result;
        if(left->val > right->val) result = right;           //确定返回的头
        else result = left;
        while(left != NULL && right != NULL){               //合并两个子序列        值得一看!
            if(left->val > right->val){
                while(right->next != NULL && right->next->val < left->val) right = right->next;
                buf = right->next;
                right->next = left;
                right = buf;
            }else{
                while(left->next != NULL && left->next->val <= right->val) left = left->next;
                buf = left->next;
                left->next = right;
                left = buf;
            }
        }
        return result;
    }
    ListNode* sortList(ListNode* head) {
        if(head == NULL) return NULL;
        if(head->next == NULL) return head;
        ListNode* buf = head;
        int a = 0;
        while(buf != NULL){ a++; buf = buf->next;}
        return sort(head,a);
    }
};

149. Max Points on a Line(Hard)

  Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

  • Example:
Input: [[1,1],[2,2],[3,3]]
Output: 3
Explanation:
^
|
|        o
|     o
|  o  
+------------->
0  1  2  3  4

Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
Output: 4
Explanation:
^
|
|  o
|     o        o
|        o
|  o        o
+------------------->
0  1  2  3  4  5  6
  • code:
/**
 * Definition for a point.
 * struct Point {
 *     int x;
 *     int y;
 *     Point() : x(0), y(0) {}
 *     Point(int a, int b) : x(a), y(b) {}
 * };
 */
class Solution {
public:
    int maxPoints(vector<Point>& points) {
        int res = 0;
        for (int i=0; i<points.size(); i++){
            int duplicate = 1;
            map<pair<int, int>, int> map;
            for (int j=i+1; j<points.size(); j++){
                if (points[j].x == points[i].x && points[j].y == points[i].y){
                    duplicate += 1;
                    continue;
                }
                int dy = points[j].y - points[i].y;
                int dx = points[j].x - points[i].x;
                int d = gcd(dy, dx);
                map[{dy/d, dx/d}] += 1;
            }
            res = max(res, duplicate);
            for (auto m : map){
                res = max(res, m.second + duplicate);
            }
        }

        return res;
    }

    int gcd(int a, int b){
        return b == 0 ? a : gcd(b, a % b);
    }
};

150. Evaluate Reverse Polish Notation(Medium)

  Evaluate the value of an arithmetic expression in Reverse Polish Notation.
  Valid operators are +, -, *, /. Each operand may be an integer or another expression.

  • Note:

    • Division between two integers should truncate toward zero.
    • The given RPN expression is always valid. That means the expression would always evaluate to a result and there won’t be any divide by zero operation.
  • Example:

Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9

Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6

Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
Output: 22
Explanation: 
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
  • code:
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> operands;
        for (string s : tokens) {
            if (s != "+" && s != "-" && s != "*" && s != "/") {
                operands.push(stoi(s));
            } else {
                int r = operands.top();
                operands.pop();
                int l = operands.top();
                operands.pop();
                if (s == "+") operands.push(l + r);
                if (s == "-") operands.push(l - r);
                if (s == "*") operands.push(l * r);
                if (s == "/") operands.push(l / r);
            }
        }
        return operands.top();
    }
};

猜你喜欢

转载自blog.csdn.net/LintaoD/article/details/81741103