致我们终将忘记的算法(贪心与动态)

1->一个三角形数组,找出从顶到底的最短路径

解题方法:从三角形的倒数第2行开始,状态转移方程f[i][j]=min(f[i][j+1],f[i+1][j+1])+(i,j);

int minmumTotal(vector<vector<int> >& triangle){

    for(int i=trangle.size()-2;i>=0;i--){

         for(int j=0;j<i+1;j++)

                 triangle[i][j]+=min(triangle[i+1][j],triangle[i+1][j+1]);

    }

    return triangle[0][0];

}

2->回文子串的最小分割

解题方法:求出所有的回文子串,采用深度搜索的方法,中间注意分割和不分割之间的区别

那么求回文子串的最小分割数,则可以采用动态规划的方法。状态转移方程f(i)=min{f(j+1)+1},i<=j<n

int minCut(string s){

    const int n=s.size();

    int f[n+1];   bool p[n][n];

    fill_n(&p[0][0],n*n,false);

    for(int i=0;i<=n;i++)   f[i]=n-1-i;

    for(int i=n-1;i>=0;i--){

          for(int j=i;j<n;j++){

                     if(s[i]==s[j] &&(j-i<2 || p[i+1][j-1])){ p[i][j]=true;  f[i]=min(f[i],f[j+1]+1;)}

                }

          }

   }

   return f[0];

}


3->判断一个字符串是否是两个字符串的组

解题方法:设状态f[i][j] 表示s1[0.i]和s2[0,j],匹配s3[0,i+j].如果s1的最后等于一个字符s3的最后一个字符,那么f[i][j]=f[i-1][j]。若s2的最后一个字符等于s3的最后一个字符,那么f[i][j]=f[i][j-1]  

bool isInterleave(string s1,string s2,string s3){

    if(s2.length()+s1.length()!=s3.length())   return false;

    bool f[s1.length()+1][s2.length()+1];

    for(int i=1;i<s1.length()+1;i++)  f[i][0]=f[i-1][0]&&s1[i-1]==s3[i-1];

    for(int i=1;i<s2.length()+1;i++) f[0][i]=f[0][i-1] &&s2[i-1]==s3[i-1];

    for(int i=1;i<=s1.length();i++)

        for(int j=1;j<=s2.length();j++)

              f[i][j]=(s1[i-1]==s3[i+j-1]&&f[i-1][j]) || (s2[j-1]==s3[i+j-1] &&f[i][j-1]);

     return f[s1.length()][s2.length()];

}


4->判断两个字符串是否互为scramble

bool isScramble(string s1,string s2){

    const int N=s1.size();

    if(N!=s2.size())  return false;

    bool f[N+1][N][N];   //表示长度为n,起点为s1[i]和起点为s2的字符串是否互为scramble

    fill_n(&f[0][0][0],(N+1)*N*N,false);

    for(int i=0;i<N;i++)

        for(int j=0;j<N;j++)

              f[1][i][j]=(s1[i]==s2[j]);

    for(int n=1;n<=N;++n)

       for(int i=0;i+n<=N;i++){

               for(int j=0;j+n<=N;j++)

                         for(int k=1;k<n;k++){

                              if(f[k][i][j]&& f[n-k][o+k][j-k] ||f[k][i][j+n-k]&& f[n-k][i+k][j]){f[n][i][j]=true; break;}

                         }

       }

     return f[N][0][0];

}


5->一个n*m矩阵从起点到终点的最短路径

动态规划的解题方法:

int minPathSum(vector<vector<int> > &grid){

    const int m=grid.size();

    const int n=grid[0].size();

     int f[m][n];

     f[0][0]=grid[0][0];

     for(int i=1;i<m;i++)

           f[i][0]=f[i-1][0]+grid[i][0];

     for(int i=1;i<n;i++)

           f[0][i]=f[0][i-1]+grid[0][i];

     for(int i=1;i<m;i++)

          for(int j=1;j<m;j++)  f[i][j]=min(f[i-1][j],f[i][j-1])+grid[i][j];

     return f[m-1][n-1];

}


6->编辑距离问题

状态式:f[i][j],表示A[0,i]和B[0,j]之间的最小编辑距离。当字符c==d时,f[i][j]=f[i-1][j-1],当字符c!=d时,有三种情况c替换d  。f[i][j]=f[i-1][j-1]+1,当在c后面添加一个d.f[i][j]=f[i][j-1]+1.当要删除c时,f[i][j]=f[i-1][j]+1;

int minDistance(const string &word1,const string &word2){

    const int n=word1.size();   const int m=word2.word2.size();

    int f[n+1][m+1];

    for(int i=0;i<=n;i++)  f[i][0]=i;

    for(int j=0;j<=m;j++) f[0][j]=j;

   for(int i=1;i<=n;i++)

     for(int j=1;j<=m;j++){

            if(word1[i-1]==word2[j-1])  f[i][j]=f[i-1][j-1];  

            else

                 int mn=min(f[i-1][j],f[i][j-1]); f[i][j]=1+min(f[i-1][j-1],mn)+1;

    }

    return f[n][m];

}


7->Decode ways

int numDecodings(const string &s){

    if(s.empty() || s[0]=='0')  return 0;

    int prev=0;  int cur=1;

    for(int i=1;i<=s.szie();i++){

           if(s[i-1]=='0') cur=0;

           if(i<2 || !(s[i-2]=='1' || (s[i-2]=='2' && s[i-1]<='6')))  prev;

           int tmp=cur;  cur=prev+cur;

          prev=cur;

    }

    return cur;

}


8->Distinct Subsequences

int numDistinct(const string &s,const string &t){

    vector<int> f(t.size()+1);

    f[0]=1;

    for(int i=0;i<s.size();i++){

          for(int j=t.size()-1;j>=0;j--)  f[j+1]+=s[i]==t[j]?f[j]:0;

    }

    return f[t.size()];

}


9->w Break

bool wordBreak(string s,set<string> &dict){

    vector<bool> f(s.size()+1,false);

    f[0]=true;

    for(int i=1;i<=s.size();i++){

         for(int j=i-1;j>=0;j--)

                  if(f[j] && dict.find(s.substr(j,i-j))!=dict.end()){ f[i]=true; break;}

    }

    return f[s.size()];

}

发布了99 篇原创文章 · 获赞 8 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/CodeAsWind/article/details/39289845