给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
提示:
1 <= S.length <= 20000S仅由小写英文字母组成。
解题思路一
按照题目要求,每找到一次两个相邻重复项,我们就可以删除掉它们。所以我们可以在字符串上从左往右移动指针,来探查相邻的两个字符是否一样,如果一样,就将其截取掉,把指针移动到这两个字符之前的字符即可。如此让指针不断在新的字符串上摇摆,直到指针指向字符串的末尾,就代表所有重复项都已经删除。
/**
* @param {string} S
* @return {string}
*/
var removeDuplicates = function(S) {
let i = 1;
while(i<S.length){
if(S[i] === S[i-1]) {
S = S.slice(0,i-1)+S.slice(i+1);
i--;
}
else i++;
}
return S;
};
需要注意的是,在 javascript 中,越界的指针会返回 undefined,所以可以利用这个特性直接比较。其他语言或许还要考虑边界的情况。
解题思路二
还有另外一种更简洁优雅的办法。对于每一个字符,都可以看作跟之前最后一个字符进行比较。换句话说,我们要在遍历中优先取找最后遍历到的字符。一种“先进后出,后进先出”的数据结构就很明显了 —— 栈。
/**
* @param {string} S
* @return {string}
*/
var removeDuplicates = function(S) {
const result = [];
for(let c of S) {
c === result[result.length-1]
? result.pop()
: result.push(c);
}
return result.join('');
};
每个新的字符都与栈顶的字符比较,如果相等,就舍弃掉,就能达到我们的目的了。
总结
这道题比较简单,也有很多的方法可以求解。但平时我们需要对基础的数据结构有更清晰的认识,往往才能利用这些特性来找出更简洁优雅的算法解决问题。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情