【LeetCode】 【dp】 回文系列

以下几题:

Leetcode 9. Palindrome Number

给定一个数字,判断数字是否为回文数字。

Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same backward as forward.

Example 1:

Input: 121
Output: true

Example 2:

Input: -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.

Example 3:

Input: 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.

1,判断回文只需要使用两个指针一前一后比较数字即可。

    bool isPalindrome(int x) {
        if(x<0 || &x==nullptr)
            return false;
        string x_str = to_string(x);
        int lo = 0;
        int hi = x_str.size()-1;
        while(lo<=hi) {
            if (x_str[lo] != x_str[hi])
                return false;
            lo++;
            hi--;
        }
        return true;
    }

这种方法需要先将int转成string,最终得分在45%左右。

2,如何不用换成字符串直接判断呢?

按照最直接的方法,回文数的定义就是数字从正序或反序来读都是一样的,那就将数字颠倒过来后再判断是否一样。

因此可以从个位数开始依次读,再不断进位相加,得到颠倒的数字。

首先保存一个输入x的备份source_x,然后对x的每一位循环,reverse_x = reverse_x*10 + x%10 的方式不断得到高位的数字。如1221可得到 reverse_x = 0*10 + 1221%10 = 1,x = x/10 = 1221/10 = 122。

    bool isPalindrome(int x) {
        if(x<0 || &x==nullptr)
            return false;
        int source_x = x;
        int reverse_x = 0;
        while(x) {
            reverse_x = reverse_x*10 + x%10;
            x = x/10;
        }
        if (source_x == reverse_x)
            return true;
        return false;
    }

 

LeetCode 5. Longest Palindromic Substring

最长回文子串。使用DP来做。

定义dp[i][j]表示从i到j的字串是否为回文串

初始化:每个单独的字母都是回文串:dp[i][i] = true

递推:判断 dp[i][j] 时,若 dp[i+1][j-1] == true 且 s[i] == s[j] ,即对于abcba,bcb是回文串且 'a' == 'a',因此 abcba 也是回文串。

注意几个地方:

1,可以看到递推时,i 由 i+1 的状态推得,因此在循环时,i 应该从大往小递推; 

2,对于两个字符的,如 'bb',中间字符串为空,因此初始化时不仅要初始化每个单个的字符 dp[i][i],也要初始化连续的两个字符 dp[i][i+1]

    string longestPalindrome(string s) {
        /*
        最长连续回文串
        使用dp,dp[i][j]表示i起点j终点的回文串长度
        */
        if (s.length() <= 1)
            return s;

        int n = s.length();
        // 首先初始化
        bool dp[n][n] = {false};
        // 所有单个字母都是回文的
        for (int i=0; i<n; i++) {
            dp[i][i] = true;
            // 两个相邻字母相等则也时回文的
            if (i<n-1)
                dp[i][i+1] = s[i]==s[i+1];
        }
        
        // 遍历每种可能
        // i应从大到小遍历
        for (int i=n-3; i>=0; i--) {      
            for(int j=i+2; j<n; j++) {
                dp[i][j] = s[i]==s[j] && dp[i+1][j-1];  // 若i与j处字符相同 且 [i+1][j-1]是回文
            }
        }
        
        int longest_length = 0;
        string longest_str = "";
        for (int i=0; i<n; i++) {
            for(int j=i; j<n; j++) {
                if (dp[i][j]==true && j-i+1>longest_length) { // 当前是回文串时 且 是目前的最长的回文串
                    longest_str = s.substr(i,j-i+1);
                    longest_length = j-i+1;
                }
            }
        }
        
        return longest_str;
    }

猜你喜欢

转载自blog.csdn.net/weixin_38628152/article/details/82854051