最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
思路
- 在JS中使用数组模拟栈
- 在新增/移除元素到栈中时,需要重新计算最小值
代码实现
/**
* @param {number} val
* @return {void}
*/
class MinStack {
constructor() {
this.list = []
// 开始赋值为无限大值Infinity
this.minStack = Infinity
}
push(val) {
this.list.push(val)
this.computedMin()
}
// 计算最小值
computedMin() {
this.min = Math.min(...this.list)
}
pop() {
const result = this.list.pop()
this.computedMin()
return result
}
top() {
return this.list[this.list.length - 1]
}
getMin() {
return this.min
}
}
删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
- 示例:
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
思路
- 遍历字符串,逐个入栈,
- 入栈时,取出栈顶元素,判断当前字符串与栈顶元素是否相等
- 如果不相等,栈顶元素再次入栈,新元素入栈
/**
* @param {string} s
* @return {string}
*/
const removeDuplicates = function (s) {
const stack = []
for (const str of s) {
const result = stack.pop()
if (result !== str) {
stack.push(result)
stack.push(str)
}
}
return stack.join('')
}
删除字符串中的所有相邻重复项 II
给你一个字符串s,「k 倍重复项删除操作」将会从s中选择k个相邻且相等的字母,并删除它们,使被删去的字符串的左侧和右侧连在一起。
你需要对s重复进行无限次这样的删除操作,直到无法继续为止。
在执行完所有删除操作后,返回最终得到的字符串。
示例1
输入:s = "abcd", k = 2
输出:"abcd"
解释:没有要删除的内容。
示例2
输入:s = "deeedbbcccbdaa", k = 3
输出:"aa"
解释:
先删除 "eee" 和 "ccc",得到 "ddbbbdaa"
再删除 "bbb",得到 "dddaa"
最后删除 "ddd",得到 "aa"
示例3
输入:s = "pbbcggttciiippooaais", k = 2
输出:"ps"
方式一:使用栈
思路
- 遍历字符串
- 移除方式取出栈顶元素
- 如果栈顶元素为空 或者 栈顶元素不包含ch
- 将栈顶元素和新字符依次压入栈
- 否则,判断
栈顶元素长度 + 1是否小于k- 小于k, 栈顶元素和ch合成新字符,再压入栈
代码
/**
* @param {string} s
* @param {number} k
* @return {string}
*/
const removeDuplicates = function (s, k) {
const stack = []
for (const ch of s) {
// 移除方式取出栈顶元素
const pre = stack.pop()
// 栈顶元素为空 或者 栈顶元素不包含ch
if (!pre || pre.indexOf(ch) === -1) {
// 将栈顶元素和新字符依次压入栈
stack.push(pre)
stack.push(ch)
} else if (pre.length + 1 < k) {
// 假设新字符串长度小于k
// 栈顶元素和ch合成新字符,再压入栈
stack.push(pre + ch)
}
}
return stack.join('')
}
删除字符串中出现次数 >= 2 次的相邻字符
示例1
输入:"abbbaca"
输出:"ca"
解释:"abbbaca" => "aaca"=>"ca"
思路
- 出现次数大于等于2的字符需要都移除
- 遍历放入栈里
- 取出栈顶的元素,取出当前字符
- 判断栈顶元素与当前字符是否相等
- 如果相等,移除栈顶元素,指针往后移动一个位置,再次判断栈顶元素与新位置的字符是否相等,直到不相等为止
- 如果不等,当前字符压入栈,指针移动一位
代码实现
/**
* 删除字符串中出现次数 >= 2 次的相邻字符
* @param {string}s
*/
function removeDuplicate(s) {
// 记录字符和对应出现的次数
const stack = []
let top
let next
let p = 0
while (p < s.length) {
top = stack[stack.length - 1]
next = s[p]
if (next === top) {
// 出现相邻字符,移除栈顶字符
stack.pop()
// 移动指针, 判断下一个元素是否等于栈顶元素,直到不相等为止
p++
while (s[p] === top) {
p++
}
} else {
stack.push(next)
p++
}
}
return stack.join('')
}