第一题(有效的括号)
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
思路:我们可以用栈来做这道题,利用栈的先进后出特性,如果遇到左括号,直接入栈,如果遇到右括号,我们先判断栈是否为空,如果为空,则表明左括号多了,然后判断匹不匹配,如果匹配就继续,不匹配则退出。最后循环走完,出来再判断栈空不空,如果不空,说明右括号多了,也返回false,走到最后一步,说明匹配上了,则返回true,代码如下
public boolean isValid(String s) {
Stack<Character> list = new Stack<>();
for(int i = 0;i < s.length();i++) {
char ch = s.charAt(i);
if(ch == '(' || ch == '{' || ch == '[') {
list.push(ch);
} else {
//右括号多的情况
if(list.empty()) {
return false;
}
char top = list.peek();
if(top=='('&&ch==')' || top=='{'&&ch=='}' || top=='['&&ch==']') {
list.pop();
} else {
//左右括号不匹配的情况
return false;
}
}
}
//左括号多的情况
if(!list.empty()) {
return false;
}
return true;
}
第二题(用队列实现栈的功能)
用两个队列实现栈,思路:放的时候往不为空的队列放,如果都为空,则指定一个放。出的时候把不为空的队列里面size-1个弄出来放入为空的那一个,再看方法,方法是top,还是pop;记下值,如果是pop弹出然后返回值即可,如果是top,弹出然后放入另一个队列,再返回值即可,代码如下
/**
* 用两个队列实现栈,思路:放的时候往不为空的队列放,如果都为空,则指定一个放
* 出的时候把不为空的队列里面size-1个弄出来放入为空的那一个,再看方法,是方法
* 是top,还是pop;记下值,如果是pop弹出然后返回值即可,如果是top,弹出然后放入
* 另一个队列,再返回值即可
*/
public class MyStack {
public Queue<Integer> qu1;
public Queue<Integer> qu2;
public MyStack() {
this.qu1 = new LinkedList<>();
this.qu2 = new LinkedList<>();
}
public void push(int x) {
if(!qu1.isEmpty()) { //往不为空的一个队列放,如果都为空,则制定一个放
qu1.offer(x);
} else if(!qu2.isEmpty()) {
qu2.offer(x);
} else {
qu1.offer(x);
}
}
public int pop() {
if(empty()) return -1; //把不为空的放入为空的,留下最后一个,最后记录然后弹出
if(!qu1.isEmpty()) {
int size = qu1.size();
for (int i = 0;i < size-1;i++) {
int a = qu1.peek();
qu1.poll();
qu2.offer(a);
}
int b = qu1.peek();
qu1.poll();
return b;
} else {
int size = qu2.size();
for (int i = 0;i < size-1;i++) {
int a = qu2.peek();
qu2.poll();
qu1.offer(a);
}
int b = qu2.peek();
qu2.poll();
return b;
}
}
public int top() {
if(empty()) return -1; //把不为空的放入为空的,留下最后一个,最后记录然后放入另一个队列
if(!qu1.isEmpty()) {
int size = qu1.size();
int value = -1;
for (int i = 0;i < size;i++) {
value = qu1.peek();
qu1.poll();
qu2.offer(value);
}
return value;
} else {
int value = -1;
int size = qu2.size();
for (int i = 0;i < size;i++) {
value = qu2.peek();
qu2.poll();
qu1.offer(value);
}
return value;
}
}
public boolean empty() {
return qu1.isEmpty() && qu2.isEmpty();
}
}
第三题(用栈实现队列的功能)
用两个栈实现队列功能,放只管往前一个栈放,出的时候出第二个,如果第二个为空,就把第一个全取出来放入第二个,然后再出,怎么出具体看方法的要求,代码如下
/**
* 用两个栈实现队列功能,放只管往前一个栈放,出的时候出第二个
* 如果第二个为空,就把第一个全取出来放入第二个,然后再出,怎么出具体看
* 方法的要求
*/
public class MyQueue {
public Stack<Integer> stack1;
public Stack<Integer> stack2;
public MyQueue() {
this.stack1 = new Stack<>();
this.stack2 = new Stack<>();
}
public void push(int x) {
stack1.push(x);
}
public int pop() {
if(stack2.empty()) {
int size = stack1.size();
for (int i = 0;i < size ;i++) {
int x= stack1.peek();
stack1.pop();
stack2.push(x);
}
int a = stack2.peek();
stack2.pop();
return a;
} else {
int a = stack2.peek();
stack2.pop();
return a;
}
}
public int peek() {
if(stack2.empty()) {
int size = stack1.size();
for (int i = 0;i < size ;i++) {
int x= stack1.peek();
stack1.pop();
stack2.push(x);
}
int a = stack2.peek();
return a;
} else {
int a = stack2.peek();
return a;
}
}
public boolean empty() {
return stack1.empty() && stack2.empty();
}
}
第四题(实现最小栈)
题目中重点是常数时间拿到最小元素。即O(1) 思路:利用辅助栈,即创建两个栈。一个为Stack,一个为MinStack;Stack功能一切正常。入栈时,需要判断这个值是否小于MinStack的最上面一个,如果MinStack为空,直接入到MinStack,否则判断大小,如果小于等于就入栈。接下来看出栈,如果出栈的值等于MinStack的peek,则MinStack也要出栈。最后top方法直接找Stack,getMin直接找MinStack即可O(1).代码如下
class MinStack {
public Stack<Integer> Stack;
public Stack<Integer> MinStack;
public MinStack() {
Stack = new Stack<>();
MinStack = new Stack<>();
}
public void push(int val) {
Stack.push(val); //入栈
if(!MinStack.empty()) { //不为空就要判断是否小于minStack或者等于上面一个
int top = MinStack.peek();
if(val <= top) { //如过满足就放进去
MinStack.push(val);
}
} else {
MinStack.push(val);
}
}
public void pop() {
int top1 = Stack.peek();
Stack.pop();
if(!MinStack.empty()) {
int top2 = MinStack.peek();
if(top1 == top2) {
MinStack.pop();
}
}
}
public int top() {
if(!Stack.empty()) {
return Stack.peek();
} throw new RuntimeException("栈中元素为空,此操作非法");
}
public int getMin() {
if(!MinStack.empty()) {
return MinStack.peek();
} throw new RuntimeException("栈中元素为空,此操作非法");
}
}
第五题(设计循环队列)
因为事例全是数字,我们用一个数组来实现。定义一个数组,一个front対首。一个rear队尾。这里我们判断满不满可以这样判断,耗费一个空间,如果rear的下一个位置是在front,即满了,如果相遇,则为空。所以构造函数创空间时,我们应该多创一个,才能放得完事例。代码如下
class MyCircularQueue {
public int[] elem;
public int front; //头
public int rear; //尾
public MyCircularQueue(int k) {
this.elem = new int[k+1];
}
public boolean enQueue(int value) {
if(isFull()) { //插入需要判断满不满
return false;
}
elem[rear] = value;
rear = (rear+1) % elem.length;
return true;
}
public boolean deQueue() {
if(isEmpty()) { //删除需要判断空不空
return false;
}
front = (front+1) % elem.length;
return true;
}
public int Front() {
if(isEmpty()) { //获取対首元素需要判断空不空
return -1;
}
return elem[front];
}
public int Rear() {
if(isEmpty()) { //获取队尾判断空不空
return -1;
}
if(rear == 0) { //0下标退格与其他地方退格不一样
return elem[elem.length-1];
} else {
return elem[rear-1];
}
}
public boolean isEmpty() {
if(rear == front) {
return true;
}
return false;
}
public boolean isFull() {
if((rear+1) % elem.length == front) {
return true;
}
return false;
}
}