Welcome to Subscribe On Youtube

Formatted question description: https://leetcode.ca/all/1745.html

1745. Palindrome Partitioning IV

Level

Hard

Description

Given a string s, return true if it is possible to split the string s into three non-empty palindromic substrings. Otherwise, return false.

A string is said to be palindrome if it the same string when reversed.

Example 1:

Input: s = “abcbdd”

Output: true

Explanation: “abcbdd” = “a” + “bcb” + “dd”, and all three substrings are palindromes.

Example 2:

Input: s = “bcbddxy”

Output: false

Explanation: s cannot be split into 3 palindromes.

Constraints:

  • 3 <= s.length <= 2000
  • s consists only of lowercase English letters.

Solution

First calculate whether each substring of s is a palindrome. Use a 2D array isPalindrome to store the results so that the results can be obtained efficiently.

Next, loop over i from 0 to s.length() - 3 and loop over j from i + 1 to s.length() - 2. If the substring from index 0 to index i is a palindrome, then check whether the substring from index i + 1 to index j and the substring from index j + 1 to index s.length() - 1 are palindromes. If such i and j exist, return true. Otherwise, return false.

  • class Solution {
        public boolean checkPartitioning(String s) {
            int length = s.length();
            boolean[][] isPalindrome = new boolean[length][length];
            for (int i = 0; i < length; i++)
                isPalindrome[i][i] = true;
            for (int i = 1; i < length; i++)
                isPalindrome[i - 1][i] = s.charAt(i - 1) == s.charAt(i);
            for (int i = length - 3; i >= 0; i--) {
                for (int j = i + 2; j < length; j++)
                    isPalindrome[i][j] = isPalindrome[i + 1][j - 1] && s.charAt(i) == s.charAt(j);
            }
            int maxFirst = length - 3, maxSecond = length - 2;
            for (int i = 0; i <= maxFirst; i++) {
                if (isPalindrome[0][i]) {
                    for (int j = i + 1; j <= maxSecond; j++) {
                        if (isPalindrome[i + 1][j] && isPalindrome[j + 1][length - 1])
                            return true;
                    }
                }
            }
            return false;
    
            /* also working, but a little lower efficiency
    
            for (int i = 0; i <= maxFirst; i++) {
                    for (int j = i + 1; j <= maxSecond; j++) {
                        if (isPalindrome[0][i] && isPalindrome[i + 1][j] && isPalindrome[j + 1][length - 1])
                            return true;
                    }
            }
            */
    
        }
    }
    
    ############
    
    class Solution {
        public boolean checkPartitioning(String s) {
            int n = s.length();
            boolean[][] g = new boolean[n][n];
            for (var e : g) {
                Arrays.fill(e, true);
            }
            for (int i = n - 1; i >= 0; --i) {
                for (int j = i + 1; j < n; ++j) {
                    g[i][j] = s.charAt(i) == s.charAt(j) && (i + 1 == j || g[i + 1][j - 1]);
                }
            }
            for (int i = 0; i < n - 2; ++i) {
                for (int j = i + 1; j < n - 1; ++j) {
                    if (g[0][i] && g[i + 1][j] && g[j + 1][n - 1]) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
    
  • // OJ: https://leetcode.com/problems/palindrome-partitioning-iv/
    // Time: O(N^2)
    // Space: O(N^2)
    class Solution {
    public:
        bool checkPartitioning(string s) {
            unsigned N = s.size(), h[2001][2001] = {}, rh[2001][2001] = {}, d = 16777619;
            for (int i = 0; i < N; ++i) {
                int hash = 0;
                for (int j = i; j < N; ++j) {
                    hash = hash * d + s[j] - 'a';
                    h[i][j] = hash;
                }
            }
            reverse(begin(s), end(s));
            for (int i = 0; i < N; ++i) {
                int hash = 0;
                for (int j = i; j < N; ++j) {
                    hash = hash * d + s[j] - 'a';
                    rh[N - j - 1][N - i - 1] = hash;
                }
            }
            for (int i = 0; i < N; ++i) { // first part [0,i]
                if (h[0][i] != rh[0][i]) continue;
                for (int j = i + 1; j < N - 1; ++j) { // second part [i+1,j], last part [j+1,N-1]
                    if (h[i + 1][j] == rh[i + 1][j] && h[j + 1][N - 1] == rh[j + 1][N - 1]) return true;
                }
            }
            return false;
        }
    };
    
  • # 1745. Palindrome Partitioning IV
    # https://leetcode.com/problems/palindrome-partitioning-iv/
    
    class Solution():
        def checkPartitioning(self, s):
            n = len(s)
    
            dp = [[False] * n for _ in range(n)]
            for i in range(n-1, -1, -1):
                for j in range(i, n):
                    if s[i] == s[j]:
                        # j-i<=2:
                        #   case-1: j-i==0, single char itself
                        #   case-12: j-i==1, e.g. 'aa'
                        #   case-1: j-i==j, e.g. 'aba'
                        dp[i][j] = (j - i <= 2) or dp[i+1][j-1]
    
            return any(dp[0][i-1] and dp[i][j-1] and dp[j][n-1] for i in range(1, n-1) for j in range(i+1, n))
    
    
    # below is 2nd solution
    from typing import List
    
    class Solution:
        def checkPartitioning(self, s: str) -> bool:
            isPalindrome = [ [False] * len(s) for i in range(len(s))]
            for i in range(len(s)):
                isPalindrome[i][i] = True
            for i in range(1, len(s)):
                isPalindrome[i - 1][i] = s[i-1] == s[i]
            for i in range(len(s) - 3, -1, -1):
                for j in range(i + 2, len(s), 1):
                    isPalindrome[i][j] = (s[i] == s[j] and isPalindrome[i + 1][j - 1])
    
            for i in range(len(s) - 2):
                for j in range(len(s) - 1):
                    if isPalindrome[0][i] and isPalindrome[i + 1][j] and isPalindrome[j + 1][len(s) - 1]:
                        return True
    
            return False
    
    if __name__ == "__main__":
        print(Solution().checkPartitioning("abcbdd"))
    
    
  • func checkPartitioning(s string) bool {
    	n := len(s)
    	g := make([][]bool, n)
    	for i := range g {
    		g[i] = make([]bool, n)
    		for j := range g[i] {
    			g[i][j] = true
    		}
    	}
    	for i := n - 1; i >= 0; i-- {
    		for j := i + 1; j < n; j++ {
    			g[i][j] = s[i] == s[j] && (i+1 == j || g[i+1][j-1])
    		}
    	}
    	for i := 0; i < n-2; i++ {
    		for j := i + 1; j < n-1; j++ {
    			if g[0][i] && g[i+1][j] && g[j+1][n-1] {
    				return true
    			}
    		}
    	}
    	return false
    }
    

All Problems

All Solutions