本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
leetcode今天的每日一题略显简单,所以另外找了一道题作为练习。
每日一题
今天的每日一题为1332. 删除回文子序列,难度为简单
-
给你一个字符串 s,它仅由字母 'a' 和 'b' 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。
-
返回删除给定字符串中所有字符(字符串为空)的最小删除次数。
-
「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。
-
「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。
由子序列的定义,我们可以得知,子序列不需要连续,和子串大不相同,并且字符串只有a和b,所以最坏的情况就是先把所以的a当做一个子序列删除,那么就只剩下b再删除一次,这样需要删除两次。当然还有好一点的情况,就是字符串s刚好为一个回文数,所以可以直接删除。这里就能知道,我们的关键点就是去判断字符串s是不是一个回文数就可以了,略显简单。
/**
* @param {string} s
* @return {number}
*/
var removePalindromeSub = function(s) {
const n = s.length;
for (let i = 0; i < Math.floor(n / 2); ++i) {
if (s[i] !== s[n - 1 - i]) {
return 2;
}
}
return 1;
};
复制代码
再来一题加大难度的相似题
由于每日一题稍微有点简单,所以找了个很相似的,更难一点的题目。
题目为leetcode上的 5. 最长回文子串 难度为 中等
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
复制代码
示例 2:
输入:s = "cbbd"
输出:"bb"
复制代码
示例 3:
输入:s = "a"
输出:"a"
复制代码
示例 4:
输入:s = "ac"
输出:"a"
复制代码
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母(大写和/或小写)组成
题解
这道题就需要注意,题目要求的子串,概念和每日一题的子序列是不一样的,子串必须是连续的。
暴力解法
首先第一种方法,最为简单的暴力解法,我们可以直接去遍历每一个子串,然后用两个变量分别纪录回文子串最大长度和最长的回文子串,每次都去判断是否满足要求然后在判断是否比保存的最长子串长,是就替换,否则就跳过。
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function (s) {
let ans = "";
let max = 0;
let len = s.length;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j <= len; j++) {
let test = s.slice(i, j);
if (isPalindrome(test) && test.length > max) {
ans = test;
max = Math.max(max, ans.length);
}
}
}
return ans;
};
function isPalindrome(s) {
let len = s.length;
for (let i = 0; i < len / 2; i++) {
if (s[i] != s[len - i - 1]) {
return false;
}
}
return true;
}
复制代码
可以看得出来,虽然成功ac了,但是运行耗时十分的久,接下去就对其进行优化
第二种题解
第二种方法我们转换一个思路,未必要去遍历每一个子字符串,对于一个字符串来说,每一个字符都可能是回文串的中心部位,所以,我们可以换一个思路,遍历字符串,在遍历的过程中去记录以每一个中心点能扩大的最大范围,最后得到的就是最长的那个子串。
这里我们要注意一个点,就是中心点,有可能是一个字符也可能是两个,比如说回文子串"aba"就是以b为中心,但是回文子串"abba"中心就变成了两个字符,以bb作为中心,所以两种情况都要判断。
/**
* @param {string} s
* @return {number}
*/
var longestPalindrome = function (s) {
let res = "";
for (let i = 0; i < s.length; i++) {
// 以s[i]为中心的最长回文串
let s1 = isPalindrome(s, i, i);
// 以s[i]和s[i+1]为中心的最长回文串
let s2 = isPalindrome(s, i, i + 1);
res = res.length > s1.length ? res : s1;
res = res.length > s2.length ? res : s2;
}
return res;
};
function isPalindrome(s, l, r) {
while (l >= 0 && r < s.length && s[l] == s[r]) {
l--;
r++;
}
return s.substr(l + 1, r - l - 1);
}
复制代码