leetcode动态规划

reverse-string

给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。
例如,给定三角形:
[
[2],
[3,4],
[6,5,7],
[4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        int layer=triangle.size();
        int result=100000;
        vector<int> tmp_min(layer,0);
        tmp_min[0]=triangle[0][0];
        for(int i=1;i<layer;i++){
            for(int j=i;j>=0;j--){
                if(j==0){
                    tmp_min[0]=tmp_min[0]+triangle[i][0];
                }else if(j==i){
                    tmp_min[i]=tmp_min[i-1]+triangle[i][i];
                }else{
                    tmp_min[j]=min(tmp_min[j-1],tmp_min[j])+triangle[i][j];
                }
            }
        }
        for(int i=0;i<layer;i++){
            if (tmp_min[i]<result){
                result=tmp_min[i];
            }
        }
        return result;
    }
};

最长连续序列

给定一个未排序的整数数组,找出最长连续序列的长度。

要求算法的时间复杂度为 O(n)。

示例:

输入: [100, 4, 200, 1, 3, 2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。

思路:用set记录元素,然后对于每一个数不断在set中找它的连续序列;如果num-1存在于set中,则不从这个数开始查找。

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        set<int> setInt;
        int result=0,tmp_result;
        for(auto num:nums){
            setInt.insert(num);
        }
        for(auto num:nums){
            auto iter=setInt.find(num-1);
            if(iter==setInt.end()){
                num+=1;
                tmp_result=1;
                while(true){
                    iter=setInt.find(num);
                    if(iter!=setInt.end()){
                        tmp_result+=1;
                    }else{
                        break;
                    }
                    num+=1;
                }
                if(tmp_result>result){
                    result=tmp_result;
                }
            }
        }
        return result;
    }
};

最小路径和

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
示例:
输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

class Solution {
public:
    int rows,cols;
    int minPathSum(vector<vector<int>>& grid) {
        rows=grid.size();
        cols=grid[0].size();
        int cur_r=0,cur_c=0;
        int pos_r,pos_c;
        int a,b;
        int max=100000000;
        while(true){
            if(cur_r+1<rows || cur_c+1<cols){
                if(cur_c+1<cols){
                    pos_r=cur_r;
                    pos_c=cur_c+1;
                    cur_r=pos_r;
                    cur_c=pos_c;
                    // cout<<"cur"<<cur_r<<cur_c<<endl;
                    while(check(pos_r,pos_c)){
                        // cout<<"pos"<<pos_r<<pos_c<<endl;
                        a=(check(pos_r-1,pos_c)) ? grid[pos_r-1][pos_c] : max;
                        b=(check(pos_r,pos_c-1)) ? grid[pos_r][pos_c-1] : max;
                        grid[pos_r][pos_c]=(a<b) ? a+grid[pos_r][pos_c]:b+grid[pos_r][pos_c];
                        pos_r+=1;
                        pos_c-=1;
                    }
                }else{
                    pos_r=cur_r+1;
                    pos_c=cur_c;
                    cur_r=pos_r;
                    cur_c=pos_c;
                    // cout<<cur_r<<cur_c<<endl;
                    while(check(pos_r,pos_c)){
                        a=(check(pos_r-1,pos_c)) ? grid[pos_r-1][pos_c] : max;
                        b=(check(pos_r,pos_c-1)) ? grid[pos_r][pos_c-1] : max;
                        grid[pos_r][pos_c]=(a<b) ? a+grid[pos_r][pos_c]:b+grid[pos_r][pos_c];
                        pos_r+=1;
                        pos_c-=1;
                    }                   
                }
            }else{
                return grid[cur_r][cur_c];
            }
        }
        return 0;
    }
    bool check(int r,int c){
        if(r>=0 && r<rows && c>=0 && c<cols ){
            return true;
        }else{
            return false;
        }
    }
};

不同路径 II

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2

class Solution {
public:
    int rows,cols;
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        auto grid=obstacleGrid;
        if(grid[0][0]==1){
            return 0;
        }
        grid[0][0]=1;
        rows=grid.size();
        cols=grid[0].size();
        int cur_r=0,cur_c=0;
        int pos_r,pos_c;
        int a,b;
        while(true){
            if(cur_r+1<rows || cur_c+1<cols){
                if(cur_c+1<cols){
                    pos_r=cur_r;
                    pos_c=cur_c+1;
                    cur_r=pos_r;
                    cur_c=pos_c;
                    // cout<<"cur"<<cur_r<<cur_c<<endl;
                    while(check(pos_r,pos_c)){
                        if (grid[pos_r][pos_c]==1){
                            grid[pos_r][pos_c]=0;
                        }else{
                            a=(check(pos_r-1,pos_c) ) ? grid[pos_r-1][pos_c] : 0;
                            b=(check(pos_r,pos_c-1)) ? grid[pos_r][pos_c-1] : 0;
                            grid[pos_r][pos_c]=a+b;
                        }
                        pos_r+=1;
                        pos_c-=1;
                    }
                }else{
                    pos_r=cur_r+1;
                    pos_c=cur_c;
                    cur_r=pos_r;
                    cur_c=pos_c;
                    // cout<<cur_r<<cur_c<<endl;
                    while(check(pos_r,pos_c)){
                        if (grid[pos_r][pos_c]==1){
                            grid[pos_r][pos_c]=0;
                        }else{
                            a=(check(pos_r-1,pos_c) ) ? grid[pos_r-1][pos_c] : 0;
                            b=(check(pos_r,pos_c-1)) ? grid[pos_r][pos_c-1] : 0;
                            grid[pos_r][pos_c]=a+b;
                        }
                        pos_r+=1;
                        pos_c-=1;
                    }             
                }
            }else{
                return grid[cur_r][cur_c];
            }
        }
        return 0;
    }
    bool check(int r,int c){
        if(r>=0 && r<rows && c>=0 && c<cols ){
            return true;
        }else{
            return false;
        }
    }
};

跳跃游戏

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个位置。
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。

思路: 维护一个可到达的最大点

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int len=nums.size();
        int range=0;
        int tmp;
        for(int i=0;i<len;i++){
            if(i<=range){
                tmp=i+nums[i];
                if(tmp>range){
                    range=tmp;
                }
            }else{
                break;
            }
        }
        if(range>=(len-1)){
            return true;
        }else{
            return false;
        }

    }
};

45. 跳跃游戏 II

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

思路: 用优先队列记录当前距离最小的节点,如果最小的节点不能到达当前节点则pop

其实更简单的方法是直接贪婪的选择能跳的更远的下一个节点


struct Pair
    {
        int range;
        int distance;
        Pair(int a,int b){
            distance=a;
            range=b;
        }
        bool operator<(const Pair& a) const
        {
            return distance>a.distance;
        }
        
    };

class Solution {
public:
    int jump(vector<int>& nums) {
        int len=nums.size();
        priority_queue<Pair> q;
        Pair first(0,nums[0]);
        q.push(first);
        int result;
        for(int i=1; i<len;i++){
            while(!q.empty()){
                auto top=q.top();
                if(top.range>=i){
                    Pair cur(top.distance+1,nums[i]+i);
                    result=top.distance+1;
                    q.push(cur);
                    break;
                }else{
                    q.pop();
                }
            }
        }
        return result;

    }
};

最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

class Solution {
public:
    string longestPalindrome(string s) {
        int len=s.size();
        if(len==1 || len==0){
            return s;
        }
        int j;
        int result=0;
        int left;
        int right;
        vector<vector<bool>> dp(len,vector<bool>(len,false));
        for (int l=1; l<=len;l++){
            for(int i=0;i<len-l+1;i++){
                j=i+l-1;
                // cout<<i<<" "<<j<<endl;
                if(l==2){
                    // cout<<"l"<<l<<endl;
                    if(s[i]==s[j]){
                        dp[i][j]=true;
                        if(l>result){
                            result=l;
                            left=i;
                            right=j;
                        }
                    }
                }else if(l==1){
                    dp[i][j]=true;
                    if(s[i]==s[j]){
                        dp[i][j]=true;
                        if(l>=result){
                            result=l;
                            left=i;
                            right=j;
                        }
                    }
                }else{
                    // cout<<i<<j<<endl;
                    // cout<<"s"<<s[i]<<s[j]<<endl;
                    // cout<<"dp"<<dp[i+1][j-1]<<endl;
                    if(s[i]==s[j] && dp[i+1][j-1]){
                            dp[i][j]=true;
                            if(l>result){
                                result=l;
                                left=i;
                                right=j;   
                            }              
                    }
                }
            }
        }
        return s.substr(left,result);
    }
};

最长公共子序列

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列的长度。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。

若这两个字符串没有公共子序列,则返回 0。

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
        int len1=text1.size();
        int len2=text2.size();
        vector<vector<int>> dp(len1+1,vector<int>(len2+1,0));
        for(int i=1;i<len1+1;i++){
            for(int j=1;j<len2+1;j++){
                if(text1[i-1]==text2[j-1]){
                    dp[i][j]=dp[i-1][j-1]+1;
                }else{
                    dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
                }
            }
        }
        return dp[len1][len2];
    }
};

编辑距离

给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
class Solution {
public:
    int minDistance(string word1, string word2) {
        int len1=word1.size();
        int len2=word2.size();
        int t;
        vector<vector<int>> dp(len1+1,vector<int>(len2+1,0));
        for(int i=0; i<len1+1;i++){
            dp[i][0]=i;
        }
        for(int i=0; i<len2+1;i++){
            dp[0][i]=i;
        }
        for(int i=1; i<len1+1;i++){
            for(int j=1;j<len2+1;j++){
                if(word1[i-1]==word2[j-1]){
                    dp[i][j]=dp[i-1][j-1];
                }else{
                    dp[i][j]=(t=dp[i-1][j-1]<=dp[i][j-1]?dp[i-1][j-1]:dp[i][j-1])<= dp[i-1][j] ? t : dp[i-1][j]; 
                    dp[i][j]+=1;
                }
            }
        }
        return dp[len1][len2];
    }
};

01背包

有 n 个物品和一个大小为 m 的背包. 给定数组 A 表示每个物品的大小和数组 V 表示每个物品的价值.

问最多能装入背包的总价值是多大?

class Solution {
public:
    /**
     * @param m: An integer m denotes the size of a backpack
     * @param A: Given n items with size A[i]
     * @return: The maximum size
     */
    int backPack(int m, vector<int> &A) {
        int cats=A.size();
        int rows=m+1, cols=cats+1;
        vector<vector<int>> dp(rows, vector<int>(cols,0));
        for(int i=1; i<m+1;i++){
            for(int j=1; j<cats+1; j++){
                if(i>=A[j-1]){
                   dp[i][j]=max(dp[i-A[j-1]][j-1]+A[j-1],dp[i][j-1]);
                }else{
                    dp[i][j]=dp[i][j-1];
                }
            }
        }
        int result=dp[m][cats];
        dp.clear();
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值