简体   繁体   中英

Longest Palindromic Substring. What could be the run time for the below DP + Recursive approach. Is it O(n^2) or O(n^3)

class Solution {

public String longestPalindrome(String s) {
    if(s.length() == 0){
        return "";
    }
    String[][] dp = new String[s.length()][s.length()];
    int n = s.length();
    for(int i=0; i<n; i++){
        dp[i][i] = s.substring(i,i+1);
    }

    int l = n/2;
    int r = n/2;
    while(!(l==0 && r==n-1)){
        if(l>0){
            l--;
        }
        if(r<n-1){
            r++;
        }
        longest(l, r, s, dp);
    }
    return dp[0][n-1];
}

public String longest(int l, int r, String s, String[][] dp) {
    if(dp[l][r] != null){
        return dp[l][r];
    } else if(s.charAt(l) == s.charAt(r) && (l == r-1 || longest(l+1, r-1, s, dp).length() == ((r-1) - (l+1))+1)){
        dp[l][r] = s.substring(l,r+1);
        return dp[l][r];
    } else {
        String l1 = longest(l, r-1, s, dp);
        String l2 = longest(l+1, r, s, dp);
        dp[l][r] = l1.length() > l2.length() ? l1 : l2;
        return dp[l][r];
    }
   }
  }

dp[i][j] represents the maximul palindromic string between indices i,j. We will finally return dp[0][s.length()-1]

Analysis of the code:

If the string (say b) is of length 1, the maximum palindrome that we can get from it would be the string itself(b). Now lets extend the string to following +b+. What would be the longest palindromic string if the + signs are substitued with some alphabets. We can consider two possibilities: i) both alphabets are same ii) both of them are different. If case i --> we can say that entire string is palindrome since we knew the string between the alphabets is completly a palindrome. If case ii --> we will have two possibilities consider left and disregard right or considering right and disregard left. The one we're looking for is the one which yeilds the maximum palindromic string.

Based on this idea we will fill up with entire dp array.

I know the space complexity for the algorithm is O(n^2) but what is the runtime complexity. Is it O(n^2) or O(n^3)?

Regarding complexity of your algo, you may want to count how many times you compute dp[l][r] (so avoid the case when you already have cached it)

  • For very big strings like 'a'.repeat(10^4) check your count.
  • Then do so for a string twice as big 'a'.repeat(2*10^4) , and check if your count is 4x or 2^3x.

That said we may do it without recursion (and seemingly more easily)

If a string of length n is a palindrome, then so is the string of length n-2 truncated left and right by 1 char.

Algorithm

The palindrome is either of even or odd length so

  • Get all 1-string, and all 2-string (with the same char in the later case)
  • To build a successor of a given string, check left and right are the same
  • continue as long as you have any successors

Complexity

Let's focus on odd length palindromes.

Assume our string is of even length.

  • We have n candidates of length 1.
  • We can build n-2 next ones (of length 3)
  • Up until we have only two candidates of length n-1

total: n + n-2 +... + 0 = sum_k=0^{n/2} (n - 2k) = n*n/2 - (n/2*(n/2+1)) ~ O(n^2)

We can double that for the palindromes of even length, thus complexity stays O(n^2)

 function pal (n) { console.time('go') const s = 'a'.repeat(n) let candidates = s.split('').map((c, i) => ({ l: i, r: i })) s.split('').forEach((c, i) => c === s[i + 1] && candidates.push({ l: i, r: i + 1 })) while(candidates.length) { const next = [] candidates.forEach(({ l, r }) => { if (l - 1 >= 0 && r + 1 < s.length && s[l - 1] === s[r + 1]) { next.push({ l: l - 1, r: r + 1 }) } }) if (next.length === 0) { // print the the biggest ones, start from the bottom... const best = candidates[candidates.length - 1] const bestLength = best.r - best.l candidates.filter(c => c.r - c.l === bestLength).forEach(c => console.log(c)) } candidates = next } console.timeEnd('go') } const base = 0.2*10**4 pal(base) // (got 1.010s with base = 0.5**10^4 but this freezes UI, so... adjust yourself to have a big enough number) pal(base*2) // expect 4 time slower (got 4.163s) pal(base*4) // expect 16 time slower (got 16.819s)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM