【LeetCode】Algorithms 题集(七)

Contains Duplicate
题意:

     Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

思路:

    找出是否有重复元素。用 set 即可。

代码:

class Solution {
public:
    bool containsDuplicate(vector<int>& nums) {
        set<int> distinct;
        vector<int>::const_iterator it = nums.begin();
        while(it != nums.end()){
            if(distinct.count(*it)) return true;
            distinct.insert(*it);
            it++;
        }
        return false;
    }
};

Generate Parentheses

题意:

      Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

      For example, given n = 3, a solution set is:

     "((()))", "(()())", "(())()", "()(())", "()()()"

思路:

       结果的数量是卡诺兰数。找出所有结果可以用递归,剪枝或者说合法结果的判断关键在于递归过程中要保证剩余右括号的数量必须大于等于左括号。

代码:

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        vector<string> ans;
        if(n == 0) return ans;
        solve(n, n, "", ans);
        return ans;
    }
    
    void solve(int l, int r, string cur, vector<string>& ans) {
        if(r < l) return;
        
        if(l == 0 && r == 0) {
            ans.push_back(cur);
            return;
        }
        
        if(l > 0) solve(l-1, r, cur+"(", ans);
        if(r > 0) solve(l, r-1, cur+")", ans);
        return;
    }
};

Binary Tree Inorder Traversal
题意:

Given a binary tree, return the inorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3

return [1,3,2].

Note: Recursive solution is trivial, could you do it iteratively?

confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.

思路:

     中序遍历非递归。

代码:

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode *root) {
        vector<int> ans;
        stack<TreeNode *> s;
        TreeNode *p = root;
        while(p != NULL || !s.empty())
        {
            while(p != NULL)
            {
                s.push(p);
                p = p->left;
            }
            if(!s.empty())
            {
                p = s.top();
                s.pop();
                ans.push_back(p->val);
                p = p->right;
            }
        }
        return ans;
    }
};


Find Minimum in Rotated Sorted Array
题意:

     Suppose a sorted array is rotated at some pivot unknown to you beforehand.

     (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

     Find the minimum element.

     You may assume no duplicate exists in the array.

思路:

      在一个以某个元素为中心点旋转之后的有序数组,找数组中最小的数。

      伪装的二分。旋转之后,数组便是先从左到右升序,然后跌落,再从左到右升序,而且右边的最高值比左边的最低值要小。

      找最小的数,我们以数组最后一个数 end 为哨兵,不断拿当前区间中间的数 mid 和 end 比较。如果 mid <= end ,说明 mid 在第二段升序区间(或者数组只有一个数),那么最小的数肯定在左边,如果 mid > end,说明 mid 在第一段升序区间,那么最小的数肯定在右边。 

代码:

class Solution {
public:
    int findMin(vector<int> &num) {
        int l = 0, r = num.size() - 1;
        int end = num[r];

        while(l<=r)
        {
            int mid = (l+r)/2;

            if(num[mid] > end)
            {
                l = mid + 1;
            }
            else
            {
                r = mid - 1;
            }
        }

        return num[l];
    }
};


Minimum Path Sum
题意:

     Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

     Note: You can only move either down or right at any point in time.

思路:

     一个矩阵每个方格都有非负权值,求从左上到右下的路径最小权值。明显 dp。但用个一维数组就好了,这里用 vector。基本的思想当然是从上往下迭代,从左往右迭代。

    为什么用一维呢?因为迭代到某个位置的时候,你只需要这个位置的左边和上边的最小权值,取出最小的那个加上矩阵这个位置的权值就好。而这个位置的迭代结果被写入之前,这个位置保存的就是上一次迭代的结果值。所以在一次从左到右的迭代过程中,一维数组里面一开始保存的全部是上次迭代的值,然后逐渐变成本次迭代的结果,最后全部被更新。

    注意矩阵第一行只能从左边到达,矩阵第一列只能从上边到达。看代码可能更清晰点。

代码:

class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        if(grid.size() == 0) return 0;
        
        int m = grid.size();
        int n = grid[0].size();
        // 初始化为矩阵第一行
        vector<int> dp(grid[0]);
        
        // 第一行的数都必须从左边到达
        for(int i = 1;i < n;++i)
            dp[i] = dp[i-1] + grid[0][i];
        
        for(int i = 1;i < m;++i) {
            // 第一列的数都必须从上面到达
            if(i != 0) dp[0] = grid[i][0] + dp[0];
            for (int j = 1;j < n;++j) {
                // 其他的数用原始矩阵的数加上左边或者上边最小的数
                dp[j] = grid[i][j] + (dp[j-1] < dp[j]? dp[j-1]: dp[j]);
            }
        }
        return dp[n-1];
    }
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值