1. Longest Substring Without Repeating Characters

思路需要 hashmap 辅助保存各个字符的位置,且随时更新最新位置

     若第 i 个位置的字符 c 出现过,则 dp[i] = min(map.get(c)-i,dp[i+1]+1)

         若没出现则 dp[i] = dp[i+1] + 1;

public int lengthOfLongestSubstring(String s) {
        if (s == null || s.length() == 0) return 0;
        Map<Character, Integer> m = new HashMap<Character, Integer>();
        int[] dp = new int[s.length()];
        dp[s.length() - 1] = 1;
        int max = 1; // 初始化dp 数组 与 返回值
        m.put(s.charAt(s.length() - 1), s.length() - 1); // 初始化 map
        for (int i = s.length() - 2; i >= 0; i--) {
            if (m.containsKey(s.charAt(i)))
                // 这里要取比较小的一个,避免出现 abbbba 这种情况,虽然间隔大,但是中间都是重复的
                dp[i] = Math.min(m.get(s.charAt(i)) - i, dp[i+1]+1); 
            else
                dp[i] = dp[i + 1] + 1;
            max = max > dp[i] ? max : dp[i];
            m.put(s.charAt(i), i); // 更新位置

        }
        return max;
    }
View Code

 2.  Longest Valid Parentheses

For "(()", the longest valid parentheses substring is "()", which has length = 2.

Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.

题目大意:找到最长的合法括号序列 ,两种形式的  "()()"  与 "((()))" 都是合法的。

思路: 若 i == ')' 设置 dp[i] = 0 即可;

      若 i == '(' ,不仅考虑 r = i+1 ; s[r]=')' 然后加上 dp[r+1]. 因为还有 "(())" 这种情况

          应该考虑 r = i + dp[i+1] + 1; 然后在考虑 dp[r+1] ;这样会考虑到 "(())" 这种情况

public int longestValidParentheses(String s) {
        if (s == null || s.length() < 2) return 0;
        int max = 0; // 弄个最大值
        int []dp = new int[s.length()];
        dp[s.length() - 1] =0; 
        for(int i = s.length() - 2 ; i >= 0 ; -- i){
            if(s.charAt(i) == '('){
                int ri = i + dp[i+1] + 1;
                if(ri < s.length() && s.charAt(ri) == ')'){
                    dp[i] = dp[ri] + dp[i+1] + 2;
                    if(ri + 1 < s.length()-1) dp[i] += dp[ri+ 1];
                }
            //else dp[i] ==0 可以省略,因为本来就 = 0
            }
            max = max > dp[i] ? max : dp[i];
        }
        return  max;
    }
View Code

3. 最长公共子串(Longest Common Substirng)

  子串是串的一个连续的部分。

 

4. 最长公共子序列(Longest Common Sequence)

  而从序列中去掉任意的元素而获得新的序列,最长子序列则可以不必连续。

//求 最长子序列的长度
    public static void LongestCommonSequence(String s1 , String s2){
        int m = s1.length();
        int n = s2.length();
        if(m == 0 || n == 0) return;
        int dp[][] = new int[m+1][n+1];
        //构建
        for(int i = 1 ; i <= m; i ++){
            for(int j = 1; j <= n; j ++){
                if(s1.charAt(i-1)== s2.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1]+1;
                }else
                    dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
            }
        }
        //查找
        String LCS = ""; int i = m,j = n;
        while (i >= 1 && j >= 1) {
            if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                char c = s1.charAt(i - 1);
                LCS = c + LCS;
                i--;
                j--;
            } else if (dp[i][j - 1] > dp[i - 1][j]) {
                j--;
            } else {
                i--;
            }
        }
        System.out.println(LCS);// 打印
    }
View Code
 思路
 1) 构建 DP 数组
    串长长度分别为m和n,创建1个二维数组L[m.n],初始化L数组内容为0,m和n分别从0开始,m++,n++循环:
       - 如果str1[m] == str2[n],则L[m,n] = L[m - 1, n -1] + 1;
       - 如果str1[m] != str2[n],则L[m,n] = max{L[m,n - 1],L[m - 1, n]}
    最后从L[m,n]中的数字一定是最大的,且这个数字就是最长公共子序列的长度
    数组L中找出一个最长的公共子序列,如果只需要找到最大长度,不需要找到具体的序列,则到这里就OK。
   2) 准确找出该串
  i 和 j 分别从m,n开始,递减循环直到i = 0,j = 0。其中,m和n分别为两个串的长度。
  如果str1[i] == str2[j],则将str[i]字符插入到子序列内,i--,j--;
  如果str1[i] != str[j],则比较L[i,j-1]与L[i-1,j]:
      L[i,j-1] > L[i-1,j],则j--,否则i--;(如果相等,则任选一个)
动态规划 Dynamic Programming
5. Interleaving String(leetcode)
  交错字符串 ,将两个字符串 s1 s2 交错起来做成一个新字符串,注意是交错的,对于如下示例, "aadbbbaccc" 是返回 false 的
动态规划 Dynamic Programming
 
    //类似于 LCS 的动态规划
    public boolean isInterleave(String s1, String s2, String s3) {
        int m = s1.length(),n = s2.length();
        if(m + n != s3.length()) return false;
        //横向放 s1 ,纵向放 s2
        boolean dp[][] = new boolean [m+1][n+1];
        dp[0][0] = true; // 把左上角元素置 true ,因为有 S1=""、 S2="" 、S3="" 的情况
        for(int i = 1 ; i < dp.length; i ++){
            if(s1.charAt(i-1) == s3.charAt(i-1)) dp[i][0] = true;
            else break;
        }
        for(int j = 1 ; j < dp[0].length; j ++){
            if(s2.charAt(j-1) == s3.charAt(j-1)) dp[0][j] = true;
            else break;
        }
        for(int i = 0 ; i < m ; i ++){
            for(int j = 0 ; j < n ; j ++){
                if(s2.charAt(j) == s3.charAt(i+j+1) && dp[i+1][j] == true){dp[i+1][j+1] = true;}
                if(s1.charAt(i) == s3.charAt(i+j+1) && dp[i][j+1] == true){dp[i+1][j+1] = true;}
            }
        }
        return dp[m][n] == true ;
    }
View Code

 6. Maximum Subarray (leetcode)

  找到和最大的连续子序列,比如对于序列 [−2,1,−3,4,−1,2,1,−5,4],和最大的连续子序列为[4,−1,2,1] ,和的最大值= 6.

 public int maxSubArray(int[] nums) {
        if(nums == null || nums.length == 0) return 0;
        int dp[] = new int[nums.length];// 动态规划数组
        dp[dp.length-1] =  nums[nums.length - 1];
        int ret = nums[nums.length - 1];// 待返回结果
        for(int i = nums.length - 2; i >= 0 ; i --){
            if(nums[i] + dp[i+1] <= nums[i]){
                dp[i] = nums[i];
            }else{
                dp[i] = dp[i+1] + nums[i];
            }
            ret = Math.max(dp[i],ret);
        }
        return ret;
    }
View Code

相关文章: