题目:
232. 用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
push
、pop
、peek
、empty
):实现
MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
说明:
- 你 只能 使用标准的栈操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例 1:
输入: ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 1, 1, false] 解释: MyQueue myQueue = new MyQueue(); myQueue.push(1); // queue is: [1] myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) myQueue.peek(); // return 1 myQueue.pop(); // return 1, queue is [2] myQueue.empty(); // return false
思路:
1.初始化栈,实现栈的基本操作push pop empty size peek等方法
2.由两个栈来模拟队列,stackin, stackout,出队列时,将stackin中的元素全部压入stackout,在pop stackout
算法:
type MyStack []int
func (s *MyStack) Push(v int) {
*s = append(*s, v)
}
func (s *MyStack) Pop() int {
val := (*s)[len(*s)-1]
*s = (*s)[:len(*s)-1]
return val
}
func (s *MyStack) Peek() int {
return (*s)[len(*s)-1]
}
func (s *MyStack) Size() int {
return len(*s)
}
func (s *MyStack) Empty() bool {
return s.Size() == 0
}
type MyQueue struct {
stackIn *MyStack
stackOut *MyStack
}
func Constructor() MyQueue {
return MyQueue {
stackIn: &MyStack{},
stackOut: &MyStack{},
}
}
func (this *MyQueue) Push(x int) {
this.stackIn.Push(x)
}
func (this *MyQueue) Pop() int {
this.FillStackOut()
return this.stackOut.Pop()
}
func (this *MyQueue) Peek() int {
this.FillStackOut()
return this.stackOut.Peek()
}
func (this *MyQueue) Empty() bool {
return this.stackIn.Empty() && this.stackOut.Empty()
}
func (this *MyQueue) FillStackOut() {
if this.stackOut.Empty() {
for !this.stackIn.Empty() {
val := this.stackIn.Pop()
this.stackOut.Push(val)
}
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* param_2 := obj.Pop();
* param_3 := obj.Peek();
* param_4 := obj.Empty();
*/
注意:
注意指针操作,注意第四行:为什么是*s,不是s?
在 Push
方法中,s
是 *MyStack
类型的接收器,表示这个方法是对栈的指针进行操作的。*s
代表指针 s
指向的实际 MyStack
类型的值。因此,使用 *s
是为了操作栈的实际数据,具体来说:
*s
解引用s
,获取栈底层的切片数据。append(*s, v)
将新元素v
添加到栈的切片中,然后将结果重新赋值给*s
。
题目:
225. 用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(
push
、top
、pop
和empty
)。实现
MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回true
;否则,返回false
。注意:
- 你只能使用队列的标准操作 —— 也就是
push to back
、peek/pop from front
、size
和is empty
这些操作。- 你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
示例:
输入: ["MyStack", "push", "push", "top", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 2, 2, false] 解释: MyStack myStack = new MyStack(); myStack.push(1); myStack.push(2); myStack.top(); // 返回 2 myStack.pop(); // 返回 2 myStack.empty(); // 返回 False
思路:
算法:
type MyStack struct {
queue []int
}
func Constructor() MyStack {
return MyStack{
queue: make([]int, 0),
}
}
func (this *MyStack) Push(x int) {
this.queue = append(this.queue, x)
}
func (this *MyStack) Pop() int {
n := len(this.queue)-1
for n != 0 {
val := this.queue[0]
this.queue = this.queue[1:]
this.queue = append(this.queue,val)
n--
}
//弹出元素
val := this.queue[0]
this.queue = this.queue[1:]
return val
}
func (this *MyStack) Top() int {
val := this.Pop()
this.queue = append(this.queue, val)
return val
}
func (this *MyStack) Empty() bool {
return len(this.queue) == 0
}
/**
* Your MyStack object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(x);
* param_2 := obj.Pop();
* param_3 := obj.Top();
* param_4 := obj.Empty();
*/
注意:
题目:
20. 有效的括号
给定一个只包括
'('
,')'
,'{'
,'}'
,'['
,']'
的字符串s
,判断字符串是否有效。有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()" 输出:true示例 2:
输入:s = "()[]{}" 输出:true示例 3:
输入:s = "(]" 输出:false提示:
1 <= s.length <= 104
s
仅由括号'()[]{}'
组成
思路:
1.用栈解题,遍历字符串,遇到( { [则将 ) } ]入栈,遇到) } ]则出栈进行对比,有三种情况不匹配,分别处理3种情况即可
算法:
func isValid(s string) bool {
stack := make([]rune,0)
m := make(map[rune]rune)
m['('] = ')'
m['['] = ']'
m['{'] = '}'
for _, v := range s {
if v == '(' || v == '{' || v== '[' {
stack = append(stack, m[v])
} else {
//遇到右括号
//若栈空了,则左括号少于右括号
if len(stack) == 0 {
return false
}
//出栈,与v(右括号)对比
peek := stack[len(stack)-1]
//不满足则匹配失败
if peek != v {
return false
}
stack = stack[:len(stack)-1]
}
}
//全部遍历完,若栈不为空,则左括号多了,return false
return len(stack) == 0
}
注意:
1.map键值对存储,注意进行比较
2.遇到左括号,则右括号入栈,这样在出栈的时候对比更直观
题目:
1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串
S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca" 输出:"ca" 解释: 例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。提示:
1 <= S.length <= 20000
S
仅由小写英文字母组成。
思路:
1.采用栈解题,遍历字符串中元素,同时与栈顶元素比较,相同则抵消,进行消消乐,不同则压入栈
算法:
func removeDuplicates(s string) string {
var ss []byte
for i := 0; i < len(s); i++ {
if len(ss) > 0 && ss[len(ss)-1] == s[i] {
ss = ss[:(len(ss)-1)]
} else {
ss = append(ss, s[i])
}
}
return string(ss)
}
注意:
1.注意s[i]类型