• 115. Distinct Subsequences


    题目:

    Given a string S and a string T, count the number of distinct subsequences of T in S.

    A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).

    Here is an example:
    S = "rabbbit", T = "rabbit"

    Return 3.

    链接: http://leetcode.com/problems/distinct-subsequences/

    题解:

    又一道读题意都很难的题目...又去discussion搬救兵了。看了以后才明白是给定pattern T, 问能在S的subsequence里有多少种包含T。很自然就又想到了dp的解法(当然是看了discussion后...)。 可以这样理解,有一个m x n的矩阵,一个机器人要从左上走到右下,只能向右或者向下走。当s.charAt(j - 1) == t.charAt(i - 1)时可以向下走, 每次向下走时count增加,向右走count不增加,,问到达右下角有多少种方法。  要注意初始化时,当 pattern = "" ,为空字符串时,第一行要初始为1。大家的理解是因为空字符串是任意字符串的subsequence。

    Time Complexity - O(mn), Space Complexity - O(mn)。

    public class Solution {
        public int numDistinct(String s, String t) {
            if(s == null || t == null)
                return 0;
            int[][] dp = new int[t.length() + 1][s.length() + 1];
            
            for(int j = 0; j < dp[0].length; j++)
                dp[0][j] = 1;
            
            for(int i = 1; i < dp.length; i++) {
                for(int j = 1; j < dp[0].length; j++) {
                    if(s.charAt(j - 1) == t.charAt(i - 1))
                        dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1];
                    else
                        dp[i][j] = dp[i][j - 1];
                }
            }
            
            return dp[t.length()][s.length()];
        }
    }

    这种只依赖上一行的dp一般都可以用滚动数组来优化space complexity, 下面是自己写的比较丑的。用到了Arrays.fill以及 clone()。 有关clone(),doc上并没有说是deep copy还是shallow copy。 在这里应该用deepcopy,不过试了一下clone()居然能work。 有时间的话还是要好好研究。

    Time Complexity - O(mn), Space Complexity - O(n)。

    public class Solution {
        public int numDistinct(String s, String t) {
            if(s == null || t == null)
                return 0;
            
            int[] last = new int[s.length() + 1];
            int[] res = new int[s.length() + 1];
            for(int j = 0; j < last.length; j++)
                last[j] = 1;
                
            for(int i = 1; i < t.length() + 1; i++) {
                for(int j = 1; j < res.length; j++) {
                    if(t.charAt(i - 1) == s.charAt(j - 1)) 
                        res[j] = res[j - 1] + last[j - 1];        
                    else 
                        res[j] = res[j - 1];
                }
                last = res.clone();
                Arrays.fill(res, 0);
            }
            
            return last[s.length()];
        }
    }

    Reference:

    https://leetcode.com/discuss/599/task-clarification

    http://www.cnblogs.com/springfor/p/3896152.html

    https://leetcode.com/discuss/19735/a-dp-solution-with-clarification-and-explanation

    https://leetcode.com/discuss/2143/any-better-solution-that-takes-less-than-space-while-in-time

    https://leetcode.com/discuss/7945/my-o-n-m-solution-for-your-reference

    https://leetcode.com/discuss/26680/easy-to-understand-dp-in-java

  • 相关阅读:
    基于MINA实现server端心跳检测(KeepAliveFilter)
    TCP的TIME_WAIT快速回收与重用
    HDU4183 起点到终点再到起点 除起点每点仅经过一次 网络流
    oracle union 注入工具
    sqlmap注入技巧收集
    sqlmap的一些小技巧
    FCKeditor漏洞利用
    WAF绕过的技巧
    杨辉三角
    Oracle 常用入侵命令
  • 原文地址:https://www.cnblogs.com/yrbbest/p/4437336.html
Copyright © 2020-2023  润新知