LeetCode【5--最长的回文子串】 LeetCode【6--Z字形变换】

最长的回文子串

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
LeetCode【5--最长的回文子串】 LeetCode【6--Z字形变换】_第1张图片

解题思路

可以跟无重复的最长子串一样,用一个滑动窗口,只不过这个窗口的右边界往右,左边界每回要从右边界的下标往左。
还需要一个二维数组记录当前窗口中记录的字符串是不是回文串
再需要一个变量记录回文串的长度。比较出最大的回文串
例如:baccab

  1. 首先定义右边界right,左边界left = right;从右边界的下标开始,如何判断当前窗口是否是回文串?第一步:判断两端值是否相等str[i] == str[j] ,第二步:判断窗口去除两端外,里面的字符串是不是回文串:s[i+1][j-1],如果长度小于3 right-left<=2,并且两端相同,那么去除两端必定为回文串 。经过上述判断则可以说明当前区间就为回文串,所以标记i~j区间中array[i][j] = true; 并记录回文串并计算长度,如果该区间长度大于之前记录的回文串的长度再记录right-left>length。res = susbtr(left,right-left+1); 从左边界开始截取长度为right - left +1的长度。length = right-left;
  2. 对于baccab来说,首先 str[right] = b ,str[left] = str[right] = b,两端相同,又因为长度小于3,所以b是回文字符串,array[i][j] =true; 此时长度大于length记录
  3. 然后right来到a的位置,left也跟着来到a的位置,开始往左走,走到b,判断两端不相同,直接下一个循环
  4. right再来到c的位置,往后依次类推…

代码实现

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        //记录字符串是否为回文字符串
        vector<vector<bool>> array (n,vector<bool>(n));
        string res = "";//记录结果返回
        int length = 0; //记录长度,比较出最长的回文子串
        if(n == 0)
            return s;
        if(n == 1)
            return s;
        //如果是两个字符,则返回第一个字符
        res = s[0]; 
        //外层循环右边界
        for(int right = 0;right<n;++right)
        {
            //内层循环左边界
            for(int left = right;left>=0;--left)
            {
                //判断是否为回文字串
                if(s[left] == s[right] //两头相等
                   && (right-left<=2 //长度小于等于3,并且两头相等比为回文串
                   ||  array[left+1][right-1]) //去掉两头,中间也是回文串才是回文串
                )
                {
                    //标记left~right该区间为回文串
                    array[left][right] = true;
                    if(right-left>length)  //如果回文串长度大于之前记录的长度,则记录该串
                    {
                        res = s.substr(left,right-left+1);
                        length = right-left; //记录新长度
                    }  
                }
            }
        }
        return res;
    }
};

Z字形变换

题目描述

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。

比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
LeetCode【5--最长的回文子串】 LeetCode【6--Z字形变换】_第2张图片
LeetCode【5--最长的回文子串】 LeetCode【6--Z字形变换】_第3张图片

解题思路

LeetCode【5--最长的回文子串】 LeetCode【6--Z字形变换】_第4张图片
一共四行numbers = 4
找规律,

  1. 第0行,0-6-12 , 间隔为6
  2. 第1行,1-5-7-11-13 间隔为4-2-4-2 奇数行
    step-2*1(行)-2*1(行)-step-2*1(行)-2*1(行)
  3. 第2行,2-4-8-10-14,间隔为2-4-2-4 偶数行
    step-2*2(行)-2*2(行)-step-2*2(行)-2*2(行)
  4. 第3行,3-9-15 ,间隔为6

第一行和和最后一行,为step = 2*numbers-2
中间是中间层的下标间距总是step-2*行数,2*行数交替

代码实现

class Solution {
public:
    string convert(string s, int numRows) {
        if(numRows == 1)  //如果只有一行数据直接返回
            return s;
        int step = numRows*2 - 2;
        string res = "";
        int index = 0; //记录每行元素的下标
        int add = 0; //中间行间隔

        for(int i = 0; i<numRows;++i)
        {
            index = i; //标记行数
            add = 2*i ; //出去第0行和numRows-1行中间行的间隔
            while(index<s.size()) //元素下标大于总个数要换行
            {
                res+=s[index];
                add = step - add ; //变换间隔,
                index += (i == 0 || i == numRows-1) ? step : add; //每行每个元素的下标都在变
            }
        }
        return res;
    }
};

你可能感兴趣的:(一些题)