栈:先进后出
队列:先进先出
232.用栈实现队列
方法名 | 作用说明 |
Enqueue(T item) | 将元素添加到队尾(入队) |
Dequeue() | 移除并返回队头元素(出队) |
Peek() | 返回队头元素但不移除 |
Contains(T item) | 判断队列中是否包含某个元素 |
Clear() | 清空队列中所有元素 |
Count | 返回当前队列中的元素数量(属性) |
ToArray() | 将队列转为数组(队头在数组[0]位置) |
TrimExcess() | 将容量设为实际元素数,释放内存 |
思路:
-
新建两个栈outstack、instack;instack用来给队列进栈,outstack用来给栈出栈
-
为了要保证出栈顺序和出队列一样 Queue:入口/出口 3→2→1 instack:入口 1→2→3 出口 outstack:入口 3→2→1 出口
public class MyQueue {
Stack<int> inStack;
Stack<int> outStack;
public MyQueue() {
inStack = new Stack<int>(); //负责进栈
outStack = new Stack<int>();//负责出栈
}
public void Push(int x) {
inStack.Push(x);
}
public int Pop() {
dumpstackIn();
return outStack.Pop();
}
public int Peek() {
dumpstackIn();
return outStack.Peek();
}
public bool Empty() {
return inStack.Count==0&&outStack.Count==0;
}
private void dumpstackIn(){
if(outStack.Count!=0){
return;
}
while(inStack.Count!=0){
outStack.Push(inStack.Pop());
}
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.Push(x);
* int param_2 = obj.Pop();
* int param_3 = obj.Peek();
* bool param_4 = obj.Empty();
*/
225. 用队列实现栈
单队列法:只使用一个队列实现栈,用到旋转队列
栈的操作:
方法名 | 功能描述 |
Push(x) | 压栈(入栈) |
Pop() | 出栈(删除栈顶元素) |
Top() | 查看栈顶元素,不删除 |
Empty() | 判断栈是否为空 |
这个循环的作用是:
-
每次把队列头的元素放到队尾;
-
把最后一个元素(原始队尾)保留在队头;
-
然后再
Dequeue()
就能模拟 “栈顶弹出” 的行为;
public class MyStack {
Queue<int> myQueue;
public MyStack() {
myQueue=new Queue<int>();
}
public void Push(int x) {
myQueue.Enqueue(x);
}
public int Pop() {
for(var i=0;i<myQueue.Count-1;i++){
myQueue.Enqueue(myQueue.Dequeue()); //先从队头取出(Dequeue),再添加到队尾(Enqueue)
}
return myQueue.Dequeue();
}
public int Top() {
int res = Pop();
myQueue.Enqueue(res);
return res;
}
public bool Empty() {
return (myQueue.Count==0);
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.Push(x);
* int param_2 = obj.Pop();
* int param_3 = obj.Top();
* bool param_4 = obj.Empty();
*/
20. 有效的括号
有三种不匹配的情况:
-
第一种情况:字符串里左方向的重复了,所以不匹配:( [ { } ] ( ) 已经遍历完了字符串,但是栈不为空,说明有相应的左字符串没有右字符串来匹配,所以返回 false
-
第二种情况:字符串中括号种类不匹配:( [ { } } } 遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以返回 false
-
第三种情况:字符串里右方向的错误了,所以不匹配:( [ { } ] ) ) ) 遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右空格找到对应的左空格return false
public class Solution {
public bool IsValid(string s) {
var stack = new Stack<char>();
//长度为奇数一定不匹配
if(s.Length%2!=0){
return false;
}
for(int i=0;i<s.Length;i++){
if(s[i]=='('){
stack.Push(')');
}
else if(s[i]=='{'){
stack.Push('}');
}
else if(s[i]=='['){
stack.Push(']');
}
//遇到情况二情况三
else{
if(stack.Count==0||stack.Peek()!=s[i]){
return false;
}
stack.Pop();
}
}
//遇到情况一
return stack.Count==0;
}
}
1047. 删除字符串中的所有相邻重复项
思路:每次读到一个字符:
-
如果它和“栈顶字符”一样,说明是相邻重复字符,→ 弹出(删除)栈顶;
-
如果不一样,就把当前字符压入栈中;
-
最后,栈中剩下的字符就是消除完所有重复后的结果。
-
可以拿字符串
StringBuilder
直接当栈,这样省去了栈还要转为字符串的操作 -
遍历字符串,如果遇到和字符串中相同,移除;不然就加入字符串;直到字符串全部遍历完
public class Solution {
public string RemoveDuplicates(string s) {
StringBuilder sb = new StringBuilder();
foreach(var i in s){
if(sb.Length>0&&sb[sb.Length-1]==i){
sb.Remove(sb.Length-1,1);
}
else{
sb.Append(i);
}
}
return sb.ToString();
}
}