Leetcode | Palindrome

Valid Palindrome

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

For example,
"A man, a plan, a canal: Panama" is a palindrome.
"race a car" is not a palindrome.

Note:
Have you consider that the string might be empty? This is a good question to ask during an interview.

For the purpose of this problem, we define empty string as valid palindrome.

处理好大小写转换、非法字符忽略就可以。

 1 class Solution {

 2 public:

 3     

 4     bool isPalindrome(string s) {

 5         if (s.empty()) return true;

 6         int l = 0, r = s.length() - 1;

 7         char c1, c2;

 8         while (r > l) {

 9             while (true) {

10                 if (l >= r) break;

11                 if (s[l] >= 'a' && s[l] <= 'z') break;

12                 if (s[l] >= 'A' && s[l] <= 'Z') { s[l] += 32; break; }

13                 if (s[l] >= '0' && s[l] <= '9') break;

14                 l++;

15             }

16             

17             while (true) {

18                 if (l >= r) break;

19                 if (s[r] >= 'a' && s[r] <= 'z') break;

20                 if (s[r] >= 'A' && s[r] <= 'Z') { s[r] += 32; break; }

21                 if (s[r] >= '0' && s[r] <= '9') break;

22                 r--;

23             }

24             

25             if (s[l] != s[r]) return false;

26             l++; r--;

27         }

28         

29         return true;

30     }

31 };

这样写好一点。

 1 class Solution {

 2 public:

 3     bool isDigit(char c) {

 4         return (c >= '0' && c <= '9');

 5     }

 6     

 7     bool isUppercase(char c) {

 8         return (c >= 'A' && c <= 'Z');

 9     }

10     

11     bool isLowercase(char c) {

12         return (c >= 'a' && c <= 'z');

13     }

14     

15     bool isValid(char c) {

16         return (isLowercase(c) || isDigit(c) || isUppercase(c));

17     }

18     

19     bool isPalindrome(string s) {

20         if (s.empty()) return true;

21         int n = s.length();

22         for (int i = 0, j = n - 1; i < j; ) {

23             for (; i < j && !isValid(s[i]); i++);

24             for (; i < j && !isValid(s[j]); j--);

25             if (isUppercase(s[i])) s[i] += 32;

26             if (isUppercase(s[j])) s[j] += 32;

27             if (s[i] != s[j]) return false;

28             i++, j--;        

29         }

30         return true;

31     }

32 };

 

Palindrome Partitioning

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"]
]

回溯法就可以了。

 1 class Solution {

 2 public:

 3     

 4     bool isPalindrome(string &s) {

 5         int n = s.length();

 6         if (n <= 1) return true;

 7         int l = 0, r = n - 1;

 8         while (r > l) {

 9             if (s[l] != s[r]) return false;

10             r--; l++;

11         }

12         return true;

13     }

14     

15     vector<vector<string>> partition(string s) {

16         vector<vector<string>> rets;

17         

18         vector<string> ret;

19         bt(s, 0, ret, rets);

20         

21         return rets;

22     }

23     

24     void bt(string &s, int index, vector<string> &ret, vector<vector<string>> &rets) {

25         if (index >= s.length()) {

26             rets.push_back(ret);

27             return;

28         }

29         

30         for (int i = index; i < s.length(); ++i) {

31             string tmp(s.substr(index, i - index + 1));

32             if (isPalindrome(tmp)) {

33                 ret.push_back(tmp);

34                 bt(s, i + 1, ret, rets);

35                 ret.pop_back();

36             }

37         }

38     }

39 };

Palindrome Partitioning II

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

Return the minimum cuts needed for a palindrome partitioning of s.

For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.

这里主要有两层需要dp的。

1. 令p[i][j]为i到j之间需要的最小cut个数。我们要求的是p[0][n - 1]。第一个dp很简单,p[i][n - 1] = min{p[j+1][n-1]} + 1, 其中i<=j<n,s(i, j)是回文。

2. 判断回文其实也是一个dp的过程,不过每次都用循环。如果s(i, j)是回文,则p[i][j]=0。p[i][j] = 0 当且仅当str[i]== str[j] && p[i + 1][j - 1]=0。没有这一部分dp就会TLE了。这一步骤用递归就可以,注意的是,比较后要设置p[i][j],无论是否等于0.

 1 class Solution {

 2 public:

 3     bool isPalindrome(string &s, int l, int r, vector<vector<int> > &p) {

 4         if (l > r) return true;

 5         if (p[l][r] == 0) return true;

 6         if (p[l][r] != -1) return false;

 7         if (s[l] != s[r]) return false;

 8         

 9         bool isPalin = isPalindrome(s, l + 1, r - 1, p);

10         if (isPalin) {

11             p[l][r] = 0;

12         } else {

13             p[l][r] = r - l;

14         }

15         return isPalin;

16     }

17     

18     int minCut(string s) {

19         int n = s.length();

20         if (n <= 1) return 0;

21         vector<vector<int> > p(n, vector<int>(n, -1));

22         for (int i = 0; i < n; ++i) {

23             p[i][i] = 0;

24         }

25         for (int i = n - 2; i >= 0; --i) {

26             p[i][n - 1] = n - i - 1;

27             for (int j = i; j < n; ++j) {

28                 if (s[j] == s[i] && isPalindrome(s, i + 1, j - 1, p)) {

29                     p[i][j] = 0;

30                     

31                     if (j < n - 1 && p[j + 1][n - 1] + 1 < p[i][n - 1]) {

32                         p[i][n - 1] = p[j + 1][n - 1] + 1;

33                     }

34                 }

35             }

36         }

37         

38         return p[0][n - 1];

39     }

40 };

 第三次写,用了两个数组。不过思路也算简单了。

 1 class Solution {

 2 public:

 3     int minCut(string s) {

 4         if (s.empty()) return 0;

 5         int n = s.length();

 6         vector<vector<bool> > dp(n, vector<bool>(n, false));

 7         vector<int> min(n, 0);

 8         for (int i = 1; i < n; ++i) {

 9             dp[i][i] = true;

10             min[i] = min[i - 1] + 1;

11             for (int j = i - 1; j >= 0; --j) {

12                 if ((j > i - 2 || dp[j + 1][i - 1]) && s[i] == s[j]) {

13                     dp[j][i] = true;

14                     if (j == 0) min[i] = 0;

15                     else if (min[j - 1] + 1 < min[i]) min[i] = min[j - 1] + 1;

16                 }

17             }

18         }

19         return min[n - 1];

20     }

21 };

空间上比起用vector<vector<int> >还是省了。因为用bool的话,最终用了O(n^2+n),用int虽然看起来只用了一个变量,但是却是O(4n^2)。

 

你可能感兴趣的:(LeetCode)