动态规划算法的运用

来源:互联网 发布:夏普阿里云电视 编辑:程序博客网 时间:2024/05/16 08:33

        今天刷OJ的时候,又遇到了用动态规划解题的例子。对这种算法的运用有了一定的认识,在此小结一下。

Leetcode: Interleaving String

Given s1s2s3, find whether s3 is formed by the interleaving of s1 and s2.

For example,
Given:
s1 = "aabcc",
s2 = "dbbca",

When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.

运用动态规划的思想,创建二维数组表,进行解题。实现代码如下:

class Solution {public:     bool isInterleave(string s1, string s2, string s3) {    if(s3.length() != s1.length() + s2.length())        return false;    bool table[s1.length()+1][s2.length()+1];    for(int i=0; i<s1.length()+1; i++)        for(int j=0; j< s2.length()+1; j++){            if(i==0 && j==0)                table[i][j] = true;            else if(i == 0)                table[i][j] = ( table[i][j-1] && s2[j-1] == s3[i+j-1]);            else if(j == 0)                table[i][j] = ( table[i-1][j] && s1[i-1] == s3[i+j-1]);            else                table[i][j] = (table[i-1][j] && s1[i-1] == s3[i+j-1] ) || (table[i][j-1] && s2[j-1] == s3[i+j-1] );        }    return table[s1.length()][s2.length()];}};

之前遇到过同样用动态规划创建二维数组解题的例子,请参见:http://blog.csdn.net/wolongdede/article/details/40017155


此外,本题还可以用递归来解,但是时间效率较低。在此附上解题代码。虽然运行时间较长,但是此代码依然具有参考性:它进行了去重处理,避免进行重复的判断,从而提高了执行效率,不至于运行超时。本人觉得其去重的处理方法十分值得学习。

public class Solution {    private static Set<Integer> visited; // The combination of i1, i2 has been visited and return false    public static boolean isInterleave(String s1, String s2, String s3) {        if(s3.length() != s1.length() + s2.length())            return false;        visited = new HashSet<Integer>();        return isInterleave(s1, 0, s2, 0, s3, 0);    }    private static boolean isInterleave(String s1, int i1, String s2, int i2, String s3, int i3)    {           int hash = i1 * s3.length() + i2;<strong>//进行去重处理,对不符合要求的i1,i2直接返回false</strong>        if(visited.contains(hash))            return false;        if(i1 == s1.length())            return s2.substring(i2).equals(s3.substring(i3));        if(i2 == s2.length())            return s1.substring(i1).equals(s3.substring(i3));        if(s3.charAt(i3) == s1.charAt(i1) && isInterleave(s1, i1+1, s2, i2, s3, i3+1) ||           s3.charAt(i3) == s2.charAt(i2) && isInterleave(s1, i1, s2, i2+1, s3, i3+1))            return true;        visited.add(hash);        return false;    }}

此代码基本思想:

The private method isInterleave is the recursive method. it takes additional i1, i2, i3 as the start indexes of s1, s2, s3, so it solves the substring of s1, s2, s3 with those start indexes.

The recursion starting condition is i1, i2, i3 are set to 0, means it solves the whole string.

in each recursion, it will just check the first character in s3 with s2 and s1, if it equals s1, it will increase i3 and i1 to solve remain, if remain return true, this recursion will also return true. Same logic for s2.

The end condition is when remain of either s1 or s2 is empty, then just compare remain of s3 with remain of s1 or s2, if they are equal, it will return true.

A pure recursive solution will cause time limit exceed. We can optimize it by caching the false visited solutions in the visited set. That will short circuit many repeated search path.



0 0
原创粉丝点击