7、栈
括号验证
思路:用栈去存储’(’ 、’{’ 、’[’,因为遇到的和栈出来的是会进行对应的,如果不对应或不存在则错误
public class StackUse{
public boolean isValid(String s) {
Stack<Character> stack=new Stack<Character>();
for (char c : s.toCharArray()){
if (c=='(' || c=='{' || c=='[') {
stack.push(c);
}
if (c==')') {
if (stack.isEmpty() && stack.pop()!=')') {
return false;
}
}
if (c=='}') {
if (stack.isEmpty() && stack.pop()!='}') {
return false;
}
}
if (c==']') {
if (stack.isEmpty() && stack.pop()!=']') {
return false;
}
}
}
return true;
}
}
最小栈
思路:建立两个栈去实现,一个栈去对应当前栈的最小值,栈值取出一个,最小栈也取出,这样就可以保证最小栈的值是正确的,不会受变化的影响
public class MinStack{
Stack<Integer> stack;
Stack<Integer> minStack;
public MinStack(){
stack=new Stack<>();
minStack=new Stack<>();
}
public void push(int value){
if(minStack.isEmpty()){
stack.push(value);
minStack.push(value);
}else{
if(value>minStack.peek()){
minStack.push(minStack.peek());
}else{
minStack.push(value);
}
stack.push(value);
}
}
public int pop(){
if(!stack.isEmpty()){
minStack.pop();
return stack.pop();
}
return -1;
}
public int min(){
if(!minStack.isEmpty()){
return minStack.peek();
}
return -1;
}
}
最大面积
思路:就是大于栈内的数,可以放入,因为可以和前面的叠一起增加x长度
而小于的就得出来,因为已经形成不了矩形,只能取出算可得的矩形面积结果
/**java
每次从栈中 pop 出一个数的时候,就找到了往左数比它小的第一个数(当前栈顶)和往右数比它小的第一个数(即将入栈的数),
从而可以计算出这两个数中间的部分宽度 * 被pop出的数,就是以这个被pop出来的数为最低的那个直方向两边展开的最大矩阵面积。
因为要计算两个数中间的宽度,因此放在 stack 里的是每个数的下标
*/
public class LargestArea {
public int largestRectangleArea(int[] height) {
if (height == null || height.length == 0) {
return 0;
}
Stack<Integer> stack = new Stack<Integer>();
int max = 0;
for (int i = 0; i < height.length; i++) {
int current =height[i];
while (!stack.isEmpty() && current <= height[stack.peek()]) {
int h = height[stack.pop()];
int w = stack.isEmpty() ? i : i - stack.peek() - 1;
max = Math.max(max, h * w);
}
stack.push(i);
}
return max;
}
}
8、队列
两个栈实现队列:
思路:用两个栈,每一次存,都先存到第一个栈,需要拿的时候,在从第一个拿出来存到第二个,这样就顺序可以反过来了
等取完第二个,再继续将第一个栈倒过去。
public class MyQueue{
//两个栈
Stack<Integer> stack1;
Stack<Integer> stack2;
public MyQueue(){
stack1=new Stack<Integer>();
stack2=new Stack<Integer>();
}
//推的时候都推到第一个
public void push(int element){
this.stack1.push(element);
}
//拿的时候
public int pop(){
if (stack1.isEmpty() && stack2.isEmpty()) {
return -1;
}
//如果第二个空的,就把第一个栈拿出来存进来
if (stack2.isEmpty()) {
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
return stack2.pop();
}
return stack2.pop();
}
public int peek(){
if (stack1.isEmpty() && stack2.isEmpty()) {
return -1;
}
//如果第二个空的,就把第一个栈拿出来存进来
if (stack2.isEmpty()) {
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
return stack2.peek();
}
return stack2.peek();
}
}
两个队列实现栈:
思路:存储的时候,先把第一个放第一队列,第二个放第二队列,然后第一队列的再加过来,接着第三个放第一队列一次进行调换。
public class MyStack {
//两个队列
Queue<Integer> queue1;
Queue<Integer> queue2;
public MyStack(){
queue1=new ArrayDeque<>();
queue2=new ArrayDeque<>();
}
//取第二队列
public int pop(){
if(queue2.isEmpty()){
return -1;
}
return queue2.poll();
}
//取第二队列的
public int peek(){
return queue2.peek();
}
public void push(int a){
//把数放入第一队列
queue1.add(a);
//然后第二队列的加进来,就可以变成后进先出
while (!queue2.isEmpty()){
queue1.add(queue2.peek());
queue2.remove();
}
//再第一队列的结果放回第二队列
Queue<Integer> queue=queue2;
queue2=queue1;
queue1=queue;
}
}