动态规划:leetcode 1039: Minimum Score Triangulation of Polygon,376:Wiggle Subsequence,678:Valid Parenthesis String

 

 

 

思路:动态规划dp[i][j]:从第i个点到第j个点的最小值。dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j]+A[i]*A[j]*A[k])

如下图:此时求dp[0][5],以(0,5)为边,在(0,5)之间遍历三角形的顶点,构成的每个三角形将原图形分为三部分:三角形,子图形1,子图形2。(默认第一个顶点序号0和最后一个顶点5是相连的)。

注意一下:边界范围,len从3到s(s为顶点数),也就是说, 当i为0时:j范围从i+2到s-1,即默认顶点0和顶点n-1是连接的。而k是在i,j的范围内一次遍历。

 

class Solution {
public:
    int minScoreTriangulation(vector<int>& A) {
        int dp[50][50];
        memset(dp, 0, sizeof(dp));
        int s = A.size();
        for(int len=3; len<=s; len++){
            for(int i=0; i+len-1<s; i++){
                int j = i+len-1;
                dp[i][j] = INT_MAX;
                for(int k=i+1; k<j; k++)
                    dp[i][j] = min(dp[i][j], dp[i][k]+dp[k][j]+A[i]*A[j]*A[k]);
            }
        }
        return dp[0][s-1];
    }
};

 

题意:寻找最长的波动数组,即输入数组中,后一个数减前一个数的差为:一正一负,或一负一正。

思路:换句话说,输入数组里的数字需要是:大小大小..... 或 小大小大..... 排列。可以设置两个数组:up[i] 和 down[i], 这里有三种情况:

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int s = nums.size();
        if(s == 0) return 0;
        int up[s], down[s];
        up[0] = down[0] = 1;
        for(int i=1; i<s; i++){
            if(nums[i]>nums[i-1]){
                down[i] = down[i-1];
                up[i] = down[i-1]+1;
            }
            else if(nums[i]<nums[i-1]){
                down[i] = up[i-1]+1;
                up[i] = up[i-1];
            }
            else{
                up[i] = up[i-1];
                down[i] = down[i-1];
            }
        }
        return max(up[s-1], down[s-1]);
    }
};

 

解法一:动态规划

1) 迭代法,自下而上,注意数组要初始化呀!

class Solution {
public:
    bool checkValidString(string s) {
        int l = s.length();
        if(l==0) return true;
        int dp[l][l];
        memset(dp, 0, sizeof(dp));
        for(int i=0; i<l;++i){
            if(s[i]=='*')
                dp[i][i] = 1;
        }
        for(int len=2; len<=l; ++len){
            for(int i=0; i<=l-len; ++i){
                int j = i+len-1;
                if((s[i]=='(' || s[i]=='*') && (s[j]==')' || s[j]=='*')){
                    if(len==2 || dp[i+1][j-1]){
                        dp[i][j] = 1;
                        continue;
                    }

                }
                
                for(int k=i;k<j;++k){
                    if(dp[i][k] && dp[k+1][j]){
                        dp[i][j] = 1;
                        break;
                    }
                }
                
            }
        }
        return dp[0][l-1];
    }
};

2)递归法:(超时了==)

class Solution {
public:

    bool checkValidString(string s) {
        int l = s.length();
        vector<vector<int>> m(l, vector<int>(l,0));
        return isValid(s,0,l-1,m);
    }
    bool isValid(string& s, int i, int j, vector<vector<int>>& m){
        if(i>j) return true;
        if(m[i][j]>0) return m[i][j];
        if(i==j) return m[i][j] = (s[i]=='*');
        if((s[i]=='('||s[i]=='*') && (s[j]==')'|| s[j]=='*')&&isValid(s,i+1,j-1,m))
            return m[i][j]=1;
        for(int k=i; k<j; ++k){
            if(isValid(s,i,k,m) && isValid(s,k+1,j,m))
                return m[i][j]=1;
        }
        return m[i][j]=0;
    }
};

解法三:这个方法是真的快!

class Solution {
public:
    bool checkValidString(string s) {
        int min_op = 0; //强制匹配左括号
        int max_op = 0; //可选匹配左括号
        for(char c:s){
            if(c=='(') 
                ++min_op;
            else
                --min_op;
            if(c!=')')
                ++max_op;
            else
                --max_op;
            if(max_op<0)
                return false;  //右括号比左括号和*加起来的数量还要多
            if(min_op<0)
                min_op = 0;
        }
        return min_op==0 ;
    }
};

 

posted @ 2019-06-27 13:11  爱学英语的程序媛  阅读(332)  评论(0编辑  收藏  举报