第一题-有效的括号
题目
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号
思路
用栈啊,一定存在一对括号直接是左右匹配的,所以,遍历字符串,遇到右括号,检查栈顶元素是否是相应的左括号,只要不匹配,就返回false,匹配的话,弹出栈顶元素,继续匹配下一项
代码
class Solution {
public boolean isValid(String s) {
Deque<Character> stack = new ArrayDeque<Character>();
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ')') {
if(!stack.isEmpty() && stack.peek() == '(') {
stack.pop();
}else {
return false;
};
}else if(!stack.isEmpty() && s.charAt(i) == '}') {
if(stack.peek() == '{') {
stack.pop();
}else {
return false;
};
}else if(!stack.isEmpty() && s.charAt(i) == ']') {
if(stack.peek() == '[') {
stack.pop();
}else {
return false;
};
}else {
stack.push(s.charAt(i));
};
};
return stack.isEmpty();
}
}
第二题-用栈实现队列-后面加两道这个的附加题
题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x)将元素 x 推到队列的末尾int pop()从队列的开头移除并返回元素int peek()返回队列开头的元素boolean empty()如果队列为空,返回true;否则,返回false
说明:
- 你 只能 使用标准的栈操作 —— 也就是只有
push to top,peek/pop from top,size, 和is empty操作是合法的。 - 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可
代码
class MyQueue {
Deque<Integer> inStack;
Deque<Integer> outStack;
public MyQueue() {
inStack = new ArrayDeque<Integer>();
outStack = new ArrayDeque<Integer>();
}
public void push(int x) {
inStack.push(x);
}
public int pop() {
if(outStack.isEmpty()) {
inToOut();
}
return outStack.pop();
}
public int peek() {
if(outStack.isEmpty()) {
inToOut();
}
return outStack.peek();
}
public boolean empty() {
if(outStack.isEmpty()) {
inToOut();
}
return outStack.isEmpty();
}
private void inToOut() {
while(!inStack.isEmpty()) {
outStack.push(inStack.pop());
};
}
}
第二题附加题01-用两个栈实现队列
题目
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
思路
感谢一直以来的坚持刷题,做这道题的时候,还有做第二题的印象,所以直接就写了
代码
class CQueue {
Deque<Integer> inStack;
Deque<Integer> outStack;
public CQueue() {
inStack = new ArrayDeque<Integer>();
outStack = new ArrayDeque<Integer>();
}
public void appendTail(int value) {
inStack.push(value);
}
public int deleteHead() {
if(outStack.isEmpty()) {
inToOut();
}
return outStack.isEmpty() ? -1 : outStack.pop();
}
public void inToOut() {
while(!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
}
}
第二题附加题02- 包含min函数的栈
题目
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)
思路
最开始思路错了,原本想设置一个全局的min,然后直接返回,但是忘记了当队列删除掉最小元素,这时的min就不在队列中了,所以参考了题解,使用栈进行存储最小元素,这个栈在我这边看来,就是单调栈
代码
class MinStack {
int minNum;
Deque<Integer> stcakTemp;
Deque<Integer> minStack;
/** initialize your data structure here. */
public MinStack() {
stcakTemp = new ArrayDeque<Integer>();
minStack = new ArrayDeque<Integer>();
minNum = 2147483647;
}
public void push(int x) {
stcakTemp.push(x);
if(minStack.isEmpty() || minStack.peek() >= x) {
minStack.push(x);
}
}
public void pop() {
if(stcakTemp.pop().equals(minStack.peek())) {
minStack.pop();
}
}
public int top() {
return stcakTemp.peek();
}
public int min() {
return minStack.peek();
}
}
第三题-树的先序遍历-根-左-右
题目
给你二叉树的根节点 root ,返回它节点值的 前序 **遍历
思路
1、递归-递归简单哎,先扔进去根结点,然后递归左子树,再递归右子树
2、morris算法-看的官方题解-(好难,好烧脑,差点放弃,多走两遍就好了)
代码
1、递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
preFun(root, list);
return list;
}
public static void preFun(TreeNode root, List list) {
if(root != null) {
list.add(root.val);
preFun(root.left, list);
preFun(root.right, list);
}else {
return;
}
}
}
2、morris
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
TreeNode p1 = root, p2 = null;
while (p1 != null) {
p2 = p1.left;
if(p2 != null) {
while(p2.right != null && p2.right != p1) {
p2 = p2.right;
}
if(p2.right == null) {
res.add(p1.val);
p2.right = p1;
p1 = p1.left;
continue;
}else {
p2.right = null;
}
}else {
res.add(p1.val);
}
p1 = p1.right;
}
return res;
}
}
第四题-树的中序遍历-左-根-右
题目
给定一个二叉树的根节点 root ,返回 它的 中序 遍历。
思路
和第三题一样的
代码
1、递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
preFun(root, list);
return list;
}
public static void preFun(TreeNode root, List list) {
if(root != null) {
preFun(root.left, list);
list.add(root.val);
preFun(root.right, list);
}else {
return;
}
}
}
2、morris
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
TreeNode p1 = root;
while(p1 != null) {
TreeNode p2 = p1.left;
if(p2 != null) {
while(p2.right != null && p2.right != p1) {
p2 = p2.right;
};
if(p2.right == null) {
p2.right = p1;
p1 = p1.left;
continue;
}else {
p2.right = null;
};
}
list.add(p1.val);
p1 = p1.right;
}
return list;
}
}
第五题-树的后序遍历
题目
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历
思路
思路同上,但是morris后序遍历我不会,也看不懂,先贴个代码,后续来看
代码
1、递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
preFun(root, list);
return list;
}
public static void preFun(TreeNode root, List list) {
if(root != null) {
preFun(root.left, list);
preFun(root.right, list);
list.add(root.val);
}else {
return;
}
}
}
2、morris
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
TreeNode p1 = root, p2 = null;
while (p1 != null) {
p2 = p1.left;
if(p2 != null) {
while(p2.right != null && p2.right != p1) {
p2 = p2.right;
}
if(p2.right == null) {
p2.right = p1;
p1 = p1.left;
continue;
}else {
p2.right = null;
printEdge(p1.left, res);
}
}
p1 = p1.right;
}
printEdge(root, res);
return res;
}
public static void printEdge(TreeNode node, List list){
TreeNode tail =reverseEdge(node);
TreeNode cur = tail;
while (cur != null ){
list.add(cur.val);
cur =cur.right;
}
reverseEdge(tail);
}
public static TreeNode reverseEdge(TreeNode node){
TreeNode pre = null;
TreeNode next = null;
while (node != null){
next = node.right;
node.right = pre;
pre = node;
node = next;
}
return pre;
}
}