牛客算法_堆栈
1、 两个栈实现一个队列
思路:
1. stack1无脑放入元素
2. 取元素时,先将stack1中的全部元素放入stack2, 然后从stack2中取元素; 在将stack2中剩余的元素放入stack1
public class StackSolution {/*** 两个stack实现队列, stack1无脑放元素,stack2负责取元素*/Stack<Integer> stack1 = new Stack<Integer>();Stack<Integer> stack2 = new Stack<Integer>();/*** @param node*/public void push(int node) {stack1.push(node);}/*** @return*/public int pop() {while (!stack1.empty()) {stack2.push(stack1.pop());}int x;if (!stack2.empty()) {x = stack2.pop();} else {x = -1;}while (!stack2.empty()) {stack1.push(stack2.pop());}return x;}
}
2、定义栈的数据结构
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。
思路:
定义两个Stack, stack1 负责栈的常规操作, stack2负责临时存储,用于min函数的实现。
注意:这个题开始不知道定义怎样的数据结构, 进入一个误区时要实现栈的数据结构就不该定义Stack类型,这是不对的。
3、括号字符串判断有效性
思路:利用栈判断
重点:边界条件的判断,pop时是否栈空, 最后返回时判断栈是否空
4、数组中找出k个不去重的最小元素(重要)
思路1:排序后取出最小的k个元素, 排序可以选择快排、归并等。(在牛客上提交的代码可以直接使用Arrays.sort(input), 这样就不用自己写排序了 )。
public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {ArrayList<Integer> list = new ArrayList<Integer>();if (k >= input.length)return copy(input);Arrays.sort(input);for (int i = 0; i < k; i++)list.add(input[i]);return list;
}
public ArrayList<Integer> copy(int[] input) {ArrayList<Integer> list = new ArrayList<Integer>();for (int i = 0; i < input.length; i++) {list.add(input[i]);}return list;
}
(需要再研究下各种排序的写法)
思路2:利用两个数据结构(栈或者其他),只存储k个元素,并记录最大最小值。在和数组的第k+1个元素比较时,如果第k+1个元素小于最大值, 这两个数据结构做拷贝,删除原先的最大值,放入当前第k+1位置的元素。
But, 测试结果正常, 但是牛客未通过。
思路3:利用大顶堆
1. 构建大顶堆:每次小于堆顶元素就将删除堆顶元素 并将新元素放进去重新调整
2. 弹出大顶堆的k个元素
(需要再研究下堆的构建和弹出的写法)
5、数组中找出第K大元素(重要)
利用快排算法,排序后找出第K大元素的下标
快排算法:
https://blog.csdn.net/qinwenjng120/article/details/152612299?sharetype=blogdetail&sharerId=152612299&sharerefer=PC&sharesource=qinwenjng120&spm=1011.2480.3001.8118
6、数据流求中位数
思路:
1. 定义数据结构,接受数据流
2. 对数据流排序
3. 取中位数
7、表达式求值(代码多)
请写一个整数计算器,支持加减乘三种运算和括号。
输入: "3+2*3*4-1"
返回值:26
思路:
1. 顺序遍历字符串
2. 连续的0~9 作为一个数字放入栈
3. 遇到 )则出栈找到( , 从而得到括号内的表达式
4. 计算括号内表达式的值并压入栈(表达式的值计算方法 calculate(Stack<String> symbols))
5. 计算栈中对应的表达式值(表达式的值计算方法 calculate(Stack<String> symbols))
注意:
1. 获取括号内表达式对应的栈时, 得到的栈做下取反,保证出栈顺序和自然顺序相反,目的是为了和最终计算栈出栈顺序保持一致(最终计算栈出栈出栈顺序和自然顺序相反)
2. Stack中元素放入String类型,方便统一处理
3. 遍历完字符串后记得判断下num是否非空,非空需要入栈
public int solve(String s) {if (s == null || s.length() <= 0) {return -1;}Stack<String> stack = new Stack();String num = "";for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);if(c >='0' && c <= '9'){num = num+ c;}else{// 数字入栈if(num.length() > 0 && Integer.valueOf(num) != null){stack.push(num);}num = "";// 遇到), 计算括号内的值,并压入栈if (c == ')') {Stack<String> contentKH = getKHContent(stack);int contentNum = calculate(contentKH);stack.push(String.valueOf(contentNum));} else { // 符号入栈stack.push(String.valueOf(c));}}}// 数字入栈if(num.length() > 0 && Integer.valueOf(num) != null){stack.push(num);}// 表达式计算return calculate(stack);}/*** 获取括号内的内容, 出栈顺序和自然顺序相反** @param stack* @return*/public Stack<String> getKHContent(Stack<String> stack) {Stack<String> temp = new Stack<String>();while (!stack.empty()) {String c = stack.pop();if (c.equals("(")) {break;}temp.push(c);}Stack<String> temp2 = new Stack<String>();while (!temp.empty()){temp2.push(temp.pop());}return temp2;}public int calculate(Stack<String> symbols) {Stack<String> symbolsTemp = new Stack();Integer rightNum;Integer leftNum;// 计算乘法while (!symbols.empty()) {String o = symbols.pop();if (strIsMulti(o) ){rightNum = Integer.valueOf(symbolsTemp.pop());leftNum = Integer.valueOf(symbols.pop());symbols.push(String.valueOf(rightNum * leftNum));} else {symbolsTemp.push(o);}}// 计算加减法while (!symbolsTemp.empty()) {String o = symbolsTemp.pop();if (strIsAddOrSub(o)) {rightNum = Integer.valueOf(symbols.pop());leftNum = Integer.valueOf(symbolsTemp.pop());if (o.equals("+")) {symbolsTemp.push(String.valueOf(rightNum + leftNum));} else {symbolsTemp.push(String.valueOf(rightNum - leftNum));}} else {symbols.push(o);}}return Integer.valueOf(symbols.peek());}public Boolean strIsMulti(String str) {return str.equals("*");}public Boolean strIsAddOrSub(String str) {return str.equals("+") || str.equals("-");}