Leetcode——02动态规划

5.最长回文子串

题目链接

踩过的坑

暴力解法超时

class Solution {
public:
    string longestPalindrome(string s) {
        string result("");//定义一个空字符串
        int sSize = int(s.size());//带判断字符串的长度
        for(int i=0;i<sSize;i++){
            int maxLength=sSize-i;//假设是回文串,最长是maxlength
            for(int tmpSize= 1;tmpSize<=maxLength;tmpSize++){
                string tmpStr= s.substr(i, tmpSize);//从当前位置到结束是否有回文串
                if(isPalindrome(tmpStr)&&tmpStr.size()>result.size()){//判断是否是回文串 且 如果是回文串该串长度与与之最长的长度比较看看哪个大
                    result=tmpStr;
                }
            }
        }
        return result;

    }

    bool isPalindrome(string s){//判断是否为回文串
        int left=0;//左指针
        int right=int(s.size())-1;//右指针
        for(;left<right;left++,right--){//指针遍历循环
            if(s[left]!=s[right]){//当不是回文串
                return false;
            }
        }
        return true;//判断完是回文串
    }
};

AC代码

参考解答

方法一:反转字符串+动态规划

class Solution {
public:
    string longestPalindrome(string s) {
       if(s==""){
           return "";//如果字符串是空
       }
       string result("");
       int sSize = int(s.size());
       string reverseS=s;
       reverse(reverseS.begin(), reverseS.end());
       vector<int> tmpVec(sSize, 0);
       vector<vector<int >> store(sSize,tmpVec);
       int maxLength = 0, end = 0;
       for(int i=0;i<sSize;i++){
           for(int j=0;j<sSize;j++){
               if(s[i] == reverseS[j]){
                   if(i==0||j==0){//动态规划,当两个元素相等时
                        store[i][j]=1;
                   }
                   else{
                       store[i][j]=store[i-1][j-1]+1;
                   }
               }

               if(store[i][j]>maxLength){//比较字符串是否来自同一个字符串
                   int preJ=sSize-1-j;
                   int nowJ=preJ+store[i][j]-1;
                   if(nowJ==i){
                       end=i;//记录位置
                       maxLength=store[i][j];//记录长度
                   }
               }
           }
       }

       result = s.substr(end+1-maxLength, maxLength);
       return result;

    }
};

方法二:动态规划

class Solution {
public:
    string longestPalindrome(string s) {
        if(s==""){
            return "";
        }
        string result("");
        int sSize=int(s.size());
        vector<bool> store(sSize, false);
        int start=0,end=0, maxLen=0;
        for(int j=0;j<sSize;j++){//动态规划store[i]从上层向下层循环
            for(int i=0;i<=j;i++){//长度为1,2的情况单独考虑
                store[i]=(s[i]==s[j]&&(j-i<3||store[i+1]));//如果s[i]==s[j]且 长度小于三或者是前一个相等时
                if(store[i]&&(j-i+1)>maxLen){//如果为true切长度大于已知的最长串时
                    maxLen=j-i+1;
                    start=i;
                    end=j;
                }
            }
        }
        result=s.substr(start, end-start+1);
        return result;

    }

  
};

方法三:中心扩展算法

方法四:马拉车算法

72. 编辑距离

编辑距离
题解

AC代码

class Solution {
public:
    int minDistance(string word1, string word2) {
        int n=word1.length();
        int m=word2.length();
        if(n*m==0) return n+m;//如果有一个字符串为空串
        int D[n+1][m+1];//dp数组
        for(int i=0;i<n+1;i++){//边界初始化
            D[i][0]=i;
        }
        for(int j=0;j<m+1;j++){
            D[0][j]=j;
        }
        //计算所有的DP值
        for(int i = 1;i< n+1;i++){
            for(int j=1;j<m+1;j++){
                int left=D[i-1][j]+1;
                int down=D[i][j-1]+1;
                int left_down=D[i-1][j-1];
                if(word1[i-1]!=word2[j-1]){
                    left_down+=1;
                }
                D[i][j]=min(left, min(down, left_down));
            }
        }

        return D[n][m];
    }
};

198. 打家劫舍

题目链接
参考答案

动态规划

class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.empty()){
            return 0;
        }
        int size=nums.size();
        if(size==1){
            return nums[0];
        }
        //动态规划找出通式
        vector<int > dp=vector<int >(size, 0);
        dp[0]=nums[0];
        dp[1]=max(nums[0],nums[1]);
        for(int i=2;i<size;i++){
            dp[i]=max(dp[i-2]+nums[i], dp[i-1]);
            
        }
        return dp[size-1];
    }
};

213. 打家劫舍 II

题目链接
分析

class Solution {
public:
    int rob(vector<int>& nums) {
        int n=nums.size();
        if(n==0){
            return 0;
        }
        else if(n<4){
            return (*max_element(nums.begin(),nums.end()));

        }
        int dp[n][2];//边界情况
        dp[0][0]=0;//没偷第0家,偷到前0家的最大金额为0;
        dp[0][1]=nums[0];//有偷第0家,偷到前0家的最大金额为nums[0];
        dp[1][1]=nums[0];//有偷第0家,偷到前0家的最大金额为nums[0]
        dp[1][0]=nums[1];//没偷第0家,偷到前1家的最大金额为nums[1]

        for(int i=2;i<n;i++){
            if(i!=n-1){
                //如果不偷最后一家,分有偷第0家和不偷第0家两条路线进行状态转移
                dp[i][0]=max(dp[i-1][0],dp[i-2][0]+nums[i]);
                dp[i][1]=max(dp[i-1][1],dp[i-2][1]+nums[i]);

            }
            else{
                //偷最后一家时,如果没有偷过第0家,可以直接选择偷或者不偷
                dp[i][0]=max(dp[i-1][0],dp[i-2][0]+nums[i]);
                //如果偷过第0家,只能选择不偷
                dp[i][1]=dp[i-1][1];
            }
        }

        //返回两种偷法中金额较大的一种
        return max(dp[n-1][0],dp[n-1][1]);


    }
};

516. 最长回文子序列

题目链接
题解

class Solution {
public:
    int longestPalindromeSubseq(string s) {
        int n=s.size();
       vector<vector<int> > f(n, vector<int>(n, 0));
       //int f[n][n];不对!!!!!!
       for(int i=0;i<n;i++) f[i][i]=1;
       for(int len=2;len<=n;len++){
           for(int i=0;i+len-1<n;i++){
               int j=i+len-1;
               if(s[i]==s[j]){
                   f[i][j]=2+f[i+1][j-1];
               }
               else{
                   f[i][j]=max(f[i+1][j],f[i][j-1]);
               }
           }
       }

        return f[0][n-1];
    }
};

674. 最长连续递增序列

题目链接

class Solution {
public:
    int findLengthOfLCIS(vector<int>& nums) {
        int n=nums.size();
        int len=1,max=0;
        if(n==0)//特例
             return 0;
        else{
            for(int i=1;i<n;i++){
                if(nums[i]>nums[i-1]){
                    len++;
                }
                else{
                    if(len>max){
                        max=len;
                    }
                    len=1;
                }
            }
            if(len>max) max=len;//连续递增的时候
               
            return max;
        }
        
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值