#20 有效的括号
public boolean isValid(String s) {
char[] chars = s.toCharArray();
if (chars.length % 2 != 0) {
return false;
}
Deque<Character> left = new LinkedList<>();
for (char aChar : chars) {
if (aChar == '(') {
left.push(')');
} else if (aChar == '[') {
left.push(']');
} else if (aChar == '{') {
left.push('}');
} else if (left.isEmpty() || left.pop() != aChar) {
return false;
}
}
return left.isEmpty();
}
#94 二叉树的中序遍历
public List<Integer> preorderTraversal(TreeNode root) {
Deque<TreeNode> stack = new LinkedList<>();
List<Integer> res = new ArrayList<>();
while (root != null || !stack.isEmpty()) {
if (root != null) {
stack.push(root);
root = root.left;
} else {
//出栈相当于递归里的为空返回
pop = stack.pop();
res.add(pop.val);
root = pop.right;
}
}
return res;
}
#144 二叉树的前序遍历
public List<Integer> preorderTraversal(TreeNode root) {
Deque<TreeNode> stack = new LinkedList<>();
List<Integer> res = new ArrayList<>();
while (root != null || !stack.isEmpty()) {
if (root != null) {
res.add(root.val);
stack.push(root);
root = root.left;
} else {
//出栈相当于递归里的为空返回
root = stack.pop().right;
}
}
return res;
}
#145 二叉树的后序遍历
public List<Integer> postorderTraversal(TreeNode root) {
Deque<TreeNode> stack = new LinkedList<>();
List<Integer> res = new ArrayList<>();
TreeNode visited = null;
while (root != null || !stack.isEmpty()) {
if (root != null) {
stack.push(root);
root = root.left;
} else {
if (stack.peek().right == null || stack.peek().right == visited) {
TreeNode pop = stack.pop();
visited = pop;
res.add(pop.val);
} else {
root = stack.peek().right;
}
}
}
return res;
}
#155 最小栈
class MinStack {
Deque<Integer> stack;
Deque<Integer> min;
public MinStack() {
stack = new LinkedList<>();
min = new LinkedList<>();
}
public void push(int val) {
stack.push(val);
if (min.isEmpty() || val < min.peek()) {
min.push(val);
}
}
public void pop() {
if (stack.pop().equals(min.peek())) {
min.pop();
}
}
public int top() {
return stack.isEmpty() ? 0 :stack.peek();
}
public int getMin() {
return min.isEmpty() ? 0 : min.peek();
}
}
#232 用栈实现队列
class MyQueue {
Deque<Integer> stack1;
Deque<Integer> stack2;
public MyQueue() {
stack1 = new LinkedList<>();
stack2 = new LinkedList<>();
}
public void push(int x) {
stack1.push(x);
}
public int pop() {
if (stack2.isEmpty()) {
pushStack2();
return stack2.pop();
}
return stack2.pop();
}
public int peek() {
if (!stack2.isEmpty()) {
return stack2.peek();
}
pushStack2();
return stack2.peek();
}
private void pushStack2() {
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
public boolean empty() {
return stack1.isEmpty() && stack2.isEmpty();
}
}
#496 下一个更大元素 I
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int[] res = new int[nums1.length];
Deque<Integer> monotoneStack = new LinkedList<>();
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums2.length; i++) {
while (!monotoneStack.isEmpty() && monotoneStack.peek() < nums2[i]) {
map.put(monotoneStack.pop(),nums2[i]);
}
monotoneStack.push(nums2[i]);
}
for (int i = 0; i < nums1.length; i++) {
res[i] = map.getOrDefault(nums1[i],-1);
}
return res;
}
#114 二叉树展开为链表
public void flatten(TreeNode root) {
while (root != null) {
TreeNode left = root.left;
TreeNode right = root.right;
TreeNode connect = left;
if (connect != null) {
while (connect.right != null) {
connect = connect.right;
}
connect.right = right;
root.right = left;
root.left = null;
}
root = root.right;
}
}
#173 二叉搜索树迭代器
static class BSTIterator {
Deque<TreeNode> stack = new LinkedList<>();
TreeNode root;
public BSTIterator(TreeNode root) {
this.root = root;
}
public int next() {
while (root != null) {
stack.push(root);
root = root.left;
}
TreeNode pop = stack.pop();
if (pop.right != null) {
root = pop.right;
}
return pop.val;
}
public boolean hasNext() {
return root != null || stack.isEmpty();
}
}
#394 字符串解码
public String decodeString(String s) {
Deque<String> multiStack = new LinkedList<>();
Deque<String> resStack = new LinkedList<>();
StringBuffer multi = new StringBuffer();
StringBuffer res = new StringBuffer();
char[] chars = s.toCharArray();
for (int i = 0; i < s.length(); i++) {
if (chars[i] >= '0' && chars[i] <= '9') {
multi.append(chars[i] - '0');
//遇到【先把【前面的数字和字符串存起来
} else if (chars[i] == '[') {
multiStack.push(multi.toString());
resStack.push(res.toString());
multi = new StringBuffer();
res = new StringBuffer();
} else if (Character.isLetter(chars[i])) {
res.append(chars[i]);
} else {
//遇到】开始拼接
int curMulti = Integer.parseInt(multiStack.pop());
String s1 = res.toString();
StringBuffer tempRes = new StringBuffer();
for (int j = 0; j < curMulti; j++) {
tempRes.append(s1);
}
res = new StringBuffer(resStack.pop() + tempRes);
}
}
return res.toString();
}
两数相加
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Deque<ListNode> stack1 = new LinkedList<>();
Deque<ListNode> stack2 = new LinkedList<>();
while (l1 != null) {
stack1.push(l1);
l1 = l1.next;
}
while (l2 != null) {
stack2.push(l2);
l2 = l2.next;
}
int carry = 0;
ListNode pre = null;
while (!stack1.isEmpty() || !stack2.isEmpty() || carry != 0) {
int a = stack1.isEmpty() ? 0 : stack1.pop().val;
int b = stack2.isEmpty() ? 0 : stack2.pop().val;
int sum = (a + b + carry)%10;
carry = (a + b + carry)/10;
ListNode listNode = new ListNode(sum);
listNode.next = pre;
pre = listNode;
}
return pre;
}
#503 下一个更大元素 II
public int[] nextGreaterElement(int[] nums1) {
int length = nums1.length;
int[] res = new int[length];
Arrays.fill(res,-1);
Deque<Integer> monotoneStack = new LinkedList<>();
for (int i = 0; i < 2 * length; i++) {
while (!monotoneStack.isEmpty() && nums1[monotoneStack.peek() % length] < nums1[i % length]) {
res[monotoneStack.pop() % length] = nums1[i % length];
}
monotoneStack.push(i);
}
return res;
}
#739 每日温度
public int[] dailyTemperatures(int[] temperatures) {
int length = temperatures.length;
int[] res = new int[length];
Deque<Integer> monotoneStack = new LinkedList<>();
for (int i = 0; i < length; i++) {
while (!monotoneStack.isEmpty() && temperatures[monotoneStack.peek()] < temperatures[i]) {
res[monotoneStack.peek()] = i - monotoneStack.pop();
}
monotoneStack.push(i);
}
return res;
}
#剑指 Offer 36 二叉搜索树与双向链表
public Node treeToDoublyList(Node root) {
Deque<Node> stack = new LinkedList<>();
Node first = null;
Node prev = null;
while (root != null || !stack.isEmpty()) {
if (root != null) {
stack.push(root);
root = root.left;
} else {
Node pop = stack.pop();
if (first == null) {
first = pop;
}
if (prev != null) {
prev.right = pop;
pop.left = prev;
}
prev = pop;
root = pop.right;
}
}
first.left = prev;
prev.right = first;
return first;
}
#剑指 Offer 31 栈的压入、弹出序列
public boolean validateStackSequences(int[] pushed, int[] popped) {
Deque<Integer> stack = new LinkedList<>();
int j = 0;
for (int i = 0; i < pushed.length; i++) {
stack.push(pushed[i]);
while (!stack.isEmpty() && stack.peek() == popped[j]) {
stack.pop();
j++;
}
}
return stack.isEmpty();
}
#42 接雨水
public int trap(int[] height) {
int res = 0;
Deque<Integer> stack = new LinkedList<>();
int cur = 0;
while (cur < height.length) {
//栈不为空并且当前高度比比栈顶高度高表示有积水开始算能装多少水
while (!stack.isEmpty() && height[cur] > height[stack.peek()]) {
//左边的墙
int h = height[stack.peek()];
stack.pop();
if (stack.isEmpty()) {
break;
}
int distance = cur - stack.peek() - 1;
int min = Math.min(height[stack.peek()],height[cur]);
res += distance * (min - h);
}
//当前高度比栈顶高度小表示装不了水
stack.push(cur);
cur++;
}
return res;
}
#84 柱状图中最大的矩形
public int largestRectangleArea(int[] heights) {
int area = 0;
int[] ints = new int[heights.length + 2];
System.arraycopy(heights,0,ints,1,heights.length);
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < ints.length; i++) {
//对于每个栈顶柱体,左侧比他小的柱体就是栈顶下面的柱体,当前柱体高度比栈顶柱体高度小,即当前柱体是比栈顶柱体高度小的右侧柱体
//找到左侧和右侧小的柱体就可以计算面积,面积是不包括左侧小的柱体和右侧小的柱体
// 例如5左侧小的柱体是1 右侧小的柱体是2 2 1 5 6 2 3 5的最大面积是5 6 不包括 1 2
//当前元素比栈顶元素小就可以算面积
while (!stack.isEmpty() && ints[i] < ints[stack.peek()]) {
area = Math.max(area,ints[stack.pop()] * (i - stack.peek() - 1));
}
//当前元素比栈顶元素大就入栈因为栈顶到栈底是单调递减的
stack.push(i);
}
return area;
}
#85 最大矩形
public int largestRectangleArea(int[] heights) {
int area = 0;
int[] ints = new int[heights.length + 2];
System.arraycopy(heights,0,ints,1,heights.length);
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < ints.length; i++) {
//对于每个栈顶柱体,左侧比他小的柱体就是栈顶下面的柱体,当前柱体高度比栈顶柱体高度小,即当前柱体是比栈顶柱体高度小的右侧柱体
//找到左侧和右侧小的柱体就可以计算面积,面积是不包括左侧小的柱体和右侧小的柱体
// 例如5左侧小的柱体是1 右侧小的柱体是2 2 1 5 6 2 3 5的最大面积是5 6 不包括 1 2
//当前元素比栈顶元素小就可以算面积
while (!stack.isEmpty() && ints[i] < ints[stack.peek()]) {
area = Math.max(area,ints[stack.pop()] * (i - stack.peek() - 1));
}
//当前元素比栈顶元素大就入栈因为栈顶到栈底是单调递减的
stack.push(i);
}
return area;
}
public int maximalRectangle(char[][] matrix) {
int[] heights = new int[matrix[0].length];
int res = 0;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j] == '1') {
heights[j] += 1;
} else {
heights[j] = 0;
}
}
res = Math.max(res,largestRectangleArea(heights));
}
return res;
}