数据机构与算法|剑指offer.09.用两个栈实现队列
用两个栈实现队列
- 前言
- 一、链表中size的问题
-
- 1、代码问题
- 2、思想优化
- 3、优化后的代码
- 4、总结
前言
在for循环中使用链表的size(),而在循环体中对链表进行增加和删除,这是会动态的影响for循环中size()的大小。一、链表中size的问题 1、代码问题
class CQueue {LinkedList l1;
LinkedList l2;
public CQueue() {l1 = new LinkedList<>();
l2 = new LinkedList<>();
}public void appendTail(int value) {l1.push(value);
}public int deleteHead() {if(l1.size() == 0)
return -1;
for(int i = 0;
i < l1.size() - 1;
i++){l2.push(l1.pop());
}
int param = l1.pop();
for(int i = 0;
i < l2.size();
i++){l1.push(l2.pop());
}
return param;
}
}
其中的for(int i = 0; i < l1.size() - 1; i++)语句中,由于循环体中不断在pop()操作,所以l1.size()并不是一个固定的值。这会导致程序得到错误的结果。2、思想优化
上面除了for循环的代码有错,其实思想也是不高效的。对于两个栈,就有两栈头可以操作,刚好对应两端受限的线性表—队列的队尾和队首。3、优化后的代码
更新后的思想:
把栈1的顶端拿来作为队列的队尾,有入队的功能;把栈2的顶端拿来作为队列的队首,有出队的功能。
1)看栈1和栈2是否同时为空,若为空,则返回-1。
2)若1)不成立,则考虑栈2是否为空,若为空,则将栈1的值push到栈2中;若不为空,则将栈2的顶端元素出栈。
class CQueue {LinkedList l1;
LinkedList l2;
public CQueue() {l1 = new LinkedList<>();
l2 = new LinkedList<>();
}public void appendTail(int value) {l1.push(value);
}public int deleteHead() {if (l1.isEmpty() && l2.isEmpty())
return -1;
if(l2.isEmpty()){while(!l1.isEmpty()){l2.push(l1.pop());
}
}
return l2.pop();
}
}
注:也可以用三元运算符代替if…else,这样会有利于CPU执行。
public int deleteHead() {if(l2.isEmpty()){while(!l1.isEmpty()){l2.push(l1.pop());
}
}
return l2.isEmpty() ? -1 : l2.pop();
}
4、总结
- 链表的size在循环中的动态改变
- 时间复杂度:O(n),每个元素只会进入一次栈1和栈2。
- 空间复杂度:O(n),最坏存入n个元素。
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- Docker应用:容器间通信与Mariadb数据库主从复制
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量
- 第326天
- Shell-Bash变量与运算符
- 参保人员因患病来不及到指定的医疗机构就医,能否报销医疗费用()
- 逻辑回归的理解与python示例
- Guava|Guava RateLimiter与限流算法
- 我和你之前距离
- CGI,FastCGI,PHP-CGI与PHP-FPM