zoukankan      html  css  js  c++  java
  • [LeetCode#131]Palindrome Partitioning

    Problem:

    Given a string s, partition s such that every substring of the partition is a palindrome.

    Return all possible palindrome partitioning of s.

    For example, given s = "aab",
    Return

      [
        ["aa","b"],
        ["a","a","b"]
      ]

    Analysis:

    This problem is a perfect combination of dynamic programming and DFS search.
    It involves many skills, and it is also easy to make mistakes if some logic is not clear and robust enough.
    
    Basic idea:
    step 1: identify all palindrome sub strings in the original string.
    step 2: use DFS to search along the checkboard, and record all available pathes.
    
    ----------------------------------------------------------------------------------
    Step 1 : dynamic programming.
    The palindrome string has a very good characteristic to use dynamic programming. The substring(p[i+1, j-1]) of a palindrome string(p[i, j]) is also a palindrome string, which means the result of a substring is palindrome or not would be used for afterward checking.
    Key: since every substring s[i, j] could be a palidrome, and i, j is random, this is a typical two dimensional dynamic programming problem. 
    Transitional function (3 cases)
    case 1: i == j      "a"
    if (i == j) {
        check_board[i][j] = true;
    } 
    
    case 2: j - i == 1    "...aa..."
    if(j - i == 1) {
        check_board[i][j] = (s.charAt(i) == s.charAt(j));
    }
    
    case 3: j - i > 1     "...aba..."
    check_board[i][j] = ((s.charAt(i) == s.charAt(j)) && check_board[i+1][j-1]);
    
    Code implementation.
    It's very easy to make mistakes when calculating the checkboard.
    Wrong way: caculate the checkboard vertically rather than horizontally. 
    for (int i = 0; i < s.length(); i++) {
        for (int j = i; j < s.length(); j++) {
            if (i == j) {
                check_board[i][j] = true;
            } else if(j - i == 1) {
                check_board[i][j] = (s.charAt(i) == s.charAt(j));
            } else{
                check_board[i][j] = ((s.charAt(i) == s.charAt(j)) && check_board[i+1][j-1]);
            }
        }
    }
    * i is the row index, j is the column index
    ----*
    00  01  02  03
        11  12  13
            22  23
                33
    The pitfall in the above solution: when we want to calculate 03, we need 12. 
    However, since we calculate row by row(vertically), 12 has not been calcualted when we reach 03. (Big pitfall)
    
    
    
    Right solution, fill the checkboard horizontally rather than vertically.
    |    00  01  02  03
    |        11  12  13
    |            22  23
    *                33
    
    Right solution:
    for (int j = 0; j < s.length(); j++) {
        for (int i = 0; i <= j; i++) {
            if (i == j) {
                check_board[i][j] = true;
            } else if(j - i == 1) {
                check_board[i][j] = (s.charAt(i) == s.charAt(j));
            } else{
                check_board[i][j] = ((s.charAt(i) == s.charAt(j)) && check_board[i+1][j-1]);
            }
        }
    }
    Skill: i is the left side of a substring, the j is the right side. 
    
    
    Step 2: DFS to search and record right path
    The same idea as subset and permutation problem.
    When we reach helper, it means s[0, start-1] all the standard of palidrome string.
    Base case: 
    if (start == len) {
        ret.add(new ArrayList<String> (path));
        return;
    }
    
    Cut-off checking and backtracking
    for (int i = start; i < len; i++) {
        if (check_board[start][i]) {
            path.add(s.substring(start, i+1));
            record_path(i+1, s, len, check_board, path, ret);
            path.remove(path.size()-1);
        }
    }

    Solution:

    public class Solution {
        public List<List<String>> partition(String s) {
            List<List<String>> ret = new ArrayList<List<String>> ();
            if (s == null || s.length() == 0) {
                ret.add(new ArrayList<String> ());
                return ret;
            }
            boolean[][] check_board = new boolean[s.length()][s.length()];
            //note the direction to reach the answer
            //vertical rather than horizontal
            for (int j = 0; j < s.length(); j++) {
                for (int i = 0; i <= j; i++) {
                    if (i == j) {
                        check_board[i][j] = true;
                    } else if(j - i == 1) {
                        check_board[i][j] = (s.charAt(i) == s.charAt(j));
                    } else{
                        check_board[i][j] = ((s.charAt(i) == s.charAt(j)) && check_board[i+1][j-1]);
                    }
                }
            }
            ArrayList<String> path = new ArrayList<String> ();
            record_path(0, s, s.length(), check_board, path, ret);
            return ret;
        }
        
        private void record_path(int start, String s, int len, boolean[][] check_board, ArrayList<String>path, List<List<String>>ret) {
            if (start == len) {
                ret.add(new ArrayList<String> (path));
                return;
            }
            for (int i = start; i < len; i++) {
                if (check_board[start][i]) {
                    path.add(s.substring(start, i+1));
                    record_path(i+1, s, len, check_board, path, ret);
                    path.remove(path.size()-1);
                }
            }
        }
    }
  • 相关阅读:
    c# winform 读取图片列表
    C# 枚举显示中文
    onenote网页版如何打开链接弄到客户端
    the error code is 2203
    unknown software exception
    无法读取配置节“protocolMapping”,因为它缺少节声明
    oracle 索引失效原因
    向 mysql 插入汉字时报错 Incorrect string value: 'xE6x9BxB9xE5x86xAC...' for col....
    (二)Linux——Linux常用指令
    (一)Linux——Linux基本概念
  • 原文地址:https://www.cnblogs.com/airwindow/p/4751760.html
Copyright © 2011-2022 走看看