• 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)。

  • 相关阅读:
    直线方程和直线系方程
    多个参数之和积的取值范围
    解析几何习题
    React之Perf
    一文看懂npm、yarn、pnpm之间的区别
    Cannot read property 'properties' of undefined
    为什么要用PolyFill(JS中的修补匠)
    es6-promise
    原生js实现each方法
    有趣的js获取input标签中光标的索引
  • 原文地址:https://www.cnblogs.com/linyx/p/3704081.html
Copyright © 2020-2023  润新知