栈【二叉树遍历】
栈
329. 仿 LISP 运算
import java.util.Scanner;
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine().replace("div", "/").replace("mul", "*")
.replace("add", "+").replace("sub", "-");
Deque<String> stack = new ArrayDeque<>();
int res = 0;
for (int i = 0; i < s.length(); i++) {
String temp = s.substring(i, i + 1);
if (!temp.equals(")")){ // 入栈
stack.push(temp);
continue;
}
StringBuilder sb = new StringBuilder();
while (!"(".equals(stack.peek())){
sb.insert(0, stack.pop());
}
String[] split = sb.toString().split(" ");
String slogan = split[0];
int a = Integer.parseInt(split[1]);
int b = Integer.parseInt(split[2]);
if ("/".equals(slogan) && b == 0){
System.out.println("error");
return;
}
res = cal(slogan, a, b);
stack.pop(); // 弹出 "("
stack.push(res + "");
}
System.out.println(res);
}
public static int cal(String str, int a, int b){
if ("/".equals(str)){
if (a / b < 0 && a % b != 0){
return a / b - 1;
}
return a / b;
}
if ("-".equals(str)){
return a - b;
}
if ("+".equals(str)){
return a + b;
}
return a * b;
}
}
263. 荒岛求生
每次加入新的时候,就要进行判断是否要进行 PK!!!
import java.util.Scanner;
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] split = in.nextLine().split(" ");
int[] arr = new int[split.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.parseInt(split[i]);
}
Deque<Integer> stack = new ArrayDeque<>();
for (int i : arr) {
if (i == 0){
System.out.println(-1);
return;
}
if (stack.isEmpty()){
stack.push(i);
continue;
}
Integer peek = stack.peek();
if (peek * i > 0){
stack.push(i);
}else { // 异号
if (peek > 0 && i < 0){ // PK
if (peek + i == 0){ // 2个全死
stack.pop();
}else {
while (!stack.isEmpty() && stack.peek() * i < 0 && stack.peek() > 0){
i = stack.pop() + i; // 待加入的
}
if (i != 0){
stack.push(i);
}
}
}else {
stack.push(i);
}
}
}
System.out.println(stack.size());
}
}
312. 二叉树中序遍历
import java.util.Scanner;
import java.util.Scanner;
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Deque<Node> stack = new ArrayDeque<>();
Scanner in = new Scanner(System.in);
String s = in.nextLine();
for (int i = 0; i < s.length(); i++) {
String now = s.substring(i, i + 1);
if (!"}".equals(now)){
if (",".equals(now)){
stack.push(new Node(","));
}else if ("{".equals(now)){
stack.push(new Node("-1"));
}else {
stack.push(new Node(now));
}
continue;
}
// 碰到了 } ==> 开始收割
List<Node> temp = new ArrayList<>();
while (!"-1".equals(stack.peek().val)){
temp.add(stack.pop());
}
stack.pop(); // 弹出 {
Node peek = stack.peek();
if (temp.size() == 3){
Node left = temp.get(2);
Node right = temp.get(0);
peek.left = left;
peek.right = right;
}else if (temp.size() == 2){
Node right = temp.get(0);
peek.right = right;
}else if (temp.size() == 1){
Node left = temp.get(0);
peek.left = left;
}
}
inOrder(stack.peek());
}
public static void inOrder(Node node){
if (node == null){
return;
}
inOrder(node.left);
System.out.print(node.val);
inOrder(node.right);
}
}
class Node{
String val;
Node left;
Node right;
public Node(String val) {
this.val = val;
}
}
数组二叉树
最小叶子节点的路径为3 7 2。
# 输入
3 5 7 -1 -1 2 4
# 输出
3 7 2
package com.ooooo;
import java.util.*;
/**
* @Author: Ronnie LEE
* @Date: 2023/10/16 - 10 - 16 - 10:12
* @Description: com.ooooo
* @version: 1.0
*/
public class Tree {
static List<TreeNode> list = new ArrayList<>();
static List<List<Integer>> lists = new ArrayList<>();
static int min = Integer.MAX_VALUE;
static StringBuilder res = new StringBuilder();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] split = in.nextLine().split(" ");
TreeNode[] arr = new TreeNode[split.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = new TreeNode(Integer.parseInt(split[i]));
}
// 找规律
// 父:i、左:2 * i,右:2 * i + 1
TreeNode left = null;
TreeNode right = null;
for (int i = 0; i < arr.length; i++) {
if (arr[i].val != -1) {
if (2 * i + 1 < arr.length && arr[2 * i + 1].val != -1) {
left = arr[2 * i + 1];
}else {
left = null;
}
if (2 * i + 2 < arr.length && arr[2 * i + 2].val != -1) {
right = arr[2 * i + 2];
}else {
right = null;
}
TreeNode treeNode = arr[i];
treeNode.left = left;
treeNode.right = right;
}
}
System.out.println(arr[0]);
dfs(arr[0]);
System.out.println("===========");
System.out.println(lists);
System.out.println(res.toString().trim());
}
public static void dfs(TreeNode treeNode){
if (treeNode == null){
return;
}
if (treeNode.left == null && treeNode.right == null){
list.add(treeNode); // TreeNode 是叶子节点
if (min > treeNode.val){
min = treeNode.val;
System.out.println("333");
res.setLength(0);
for (TreeNode node : list) {
res.append(node.val + " ");
}
}
List<Integer> temp = new ArrayList<>();
for (TreeNode node : list) {
temp.add(node.val);
}
lists.add(new ArrayList<>(temp));
Tree.list.remove(Tree.list.size() - 1); // 回溯!!!
return;
}
list.add(treeNode);
dfs(treeNode.left);
dfs(treeNode.right);
}
}
class TreeNode{
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
@Override
public String toString() {
return "TreeNode{" +
"val=" + val +
", left=" + left +
", right=" + right +
'}';
}
}
完全二叉树非叶子部分后序遍历
import java.util.Scanner;
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
static int[] arr;
static StringBuilder res = new StringBuilder();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] split = in.nextLine().split(" ");
arr = new int[split.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.parseInt(split[i]);
}
Node root = getRoot(0);
if (root.left == null && root.right == null){ // 特殊情况:只有一个根节点
System.out.println(root.val);
return;
}
backtracking(root);
System.out.println(res.toString().trim());
}
public static void backtracking(Node node){
if (node == null){
return;
}
if (node.left == null && node.right == null){
return;
}
backtracking(node.left);
backtracking(node.right);
res.append(node.val + " ");
}
public static Node getRoot(int i){
Node node = new Node(arr[i]);
if (2 * i + 1 < arr.length){
node.left = getRoot(2 * i + 1);
}
if (2 * i + 2 < arr.length){
node.right = getRoot(2 * i + 2);
}
return node;
}
}
class Node{
int val;
Node left;
Node right;
public Node(int val) {
this.val = val;
}
}
二叉树的广度优先遍历
package com.lllp;
import javax.swing.tree.TreeNode;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;
/**
* @Author: Ronnie LEE
* @Date: 2023/10/16 - 10 - 16 - 16:56
* @Description: com.lllp
* @version: 1.0
*/
public class ooo {
// CBEFDA:后序
// CBAEDF:中序
static String strA;
static Deque<Node> deque = new ArrayDeque<>();
static StringBuilder res = new StringBuilder();
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] split = in.nextLine().split(" ");
strA = split[0];
Node node = getNode(split[1]);
System.out.println(node);
deque.offer(node);
bfs();
System.out.println(res);
}
public static Node getNode(String strB){ // 中序
int index = -1;
for (int i = strA.length(); i >= 1; i--) {
String root = strA.substring(i - 1, i);
if (strB.contains(root)){
index = strB.indexOf(root);
break;
}
}
Node node = new Node(strB.substring(index, index + 1));
String left = strB.substring(0, index);
if (!"".equals(left)){
node.left = getNode(left);
}
String right = strB.substring(index + 1); // 这里无需特殊处理,substring 第一个参数可以等于长度,这样得到的结果就是 ""
if (!"".equals(right)){
node.right = getNode(right);
}
return node;
}
public static void bfs(){
while (!deque.isEmpty()){
int size = deque.size();
while (size > 0){
Node node = deque.poll();
res.append(node.val);
if (node.left != null){
deque.offer(node.left);
}
if (node.right != null){
deque.offer(node.right);
}
size--;
}
}
}
}
class Node{
String val;
Node left;
Node right;
public Node(String val) {
this.val = val;
}
@Override
public String toString() {
return "Node{" +
"val='" + val + '\'' +
", left=" + left +
", right=" + right +
'}';
}
}
327. 二维伞的雨滴效应
import java.util.Scanner;
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String[] split = in.nextLine().split(" ");
int[] arr = new int[split.length];
// 判断是否是 BST:是否是 BST 的前序遍历【根 左 右】
// 中序【左 根 右】
List<Integer> temp = new ArrayList<>();
List<Integer> list = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.parseInt(split[i]);
temp.add(arr[i]);
list.add(arr[i]);
}
Collections.sort(list);
// 不是 BST的 情形
if (!isValid(arr, 0, arr.length - 1, Integer.MIN_VALUE, Integer.MAX_VALUE)){
System.out.println(0 + " " + 0 + " " + 0);
return;
}
TreeNode root = getRoot(arr, list);
if (root.val == getLeft(root, 0).val && root.val != getRight(root, 0).val){
System.out.println("1" + " " + 0 + " " + getRight(root, 0).val);
return;
}
if (root.val != getLeft(root, 0).val && root.val == getRight(root, 0).val){
System.out.println("1" + " " + getLeft(root, 0).val + " " + 0);
return;
}
if (root.val == getLeft(root, 0).val && root.val == getRight(root, 0).val){
System.out.println("1" + " " + 0 + " " + 0);
return;
}
System.out.println("1" + " " + getLeft(root, 0).val + " " + getRight(root, 0).val);
}
public static TreeNode getRoot(int[] arr, List<Integer> list){
int index = -1;
for (int i = 0; i < arr.length; i++) {
if (list.contains(arr[i])){
index = Collections.binarySearch(list, arr[i]);// 以根节点进行分割
break;
}
}
TreeNode treeNode = new TreeNode(list.get(index));
List<Integer> left = list.subList(0, index);
if (left.size() > 0){
treeNode.left = getRoot(arr, left);
}
List<Integer> right = list.subList(index + 1, list.size());
if (right.size() > 0){
treeNode.right = getRoot(arr, right);
}
return treeNode;
}
public static TreeNode getLeft(TreeNode root, int len){
if (root.left == null){
if (len == 0){
return root;
}else {
if (root.right != null){
return getLeft(root.right, len + 1);
}
}
}else {
return getLeft(root.left, len + 1);
}
return root;
}
public static TreeNode getRight(TreeNode root, int len){
if (root.right == null){
if (len == 0){
return root;
}else {
if (root.left != null){
return getRight(root.left, len + 1);
}
}
}else {
return getRight(root.right, len + 1);
}
return root;
}
public static boolean isValid(int[] arr, int start, int end, int min, int max){
if (start > end){ // 当前没有左子树,正确
return true;
}
int rootValue = arr[start];
if (rootValue < min || rootValue > max){
return false;
}
int index = start;
while (index + 1 <= end && arr[index + 1] <= rootValue){
index++; // 截断点
}
boolean leftSubtree = isValid(arr, start + 1, index, min, rootValue - 1);
boolean rightSubtree = isValid(arr, index + 1, end, rootValue + 1, max);
return leftSubtree && rightSubtree;
}
}
class TreeNode{
int val; // 输入的数组的任意两个数字都互不相同
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
662. 二叉树最大宽度【BFS:为每一个节点配置对应的下标】
/**
* 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 {
Deque<TreeNode> deque = new ArrayDeque<>();
int res = 0;
List<Integer> list = new ArrayList<>(); // 存储下标!!!
public int widthOfBinaryTree(TreeNode root) {
// 每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度
// 结合 二叉树 的数组表示
list.add(1);
deque.offer(root);
bfs();
return res;
}
public void bfs(){
while (!deque.isEmpty()){
int len = deque.size();
while (len > 0) {
TreeNode peek = deque.poll();
int index = list.get(0);
list.subList(0, 1).clear(); // 弹出第一个坐标
if (peek.left != null){
deque.offer(peek.left);
list.add(2 * index); // 左孩子下标 【相当于为每一个节点,设置了和它相匹配的下标】
}
if (peek.right != null){
deque.offer(peek.right);
list.add(2 * index + 1); // 右孩子下标
}
len--;
}
if (list.size() == 1 || list.size() == 0){
res = Math.max(res, 1);
}else {
res = Math.max(res, list.get(list.size() - 1) - list.get(0) + 1); // 由于是求个数:所以 + 1
}
}
}
}
155. 最小栈【栈中存放的是:数组】
class MinStack {
Deque<Integer[]> stack;
// 设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
public MinStack() {
stack = new ArrayDeque<>();
}
public void push(int val) {
if (stack.isEmpty()){
stack.push(new Integer[]{val, val});
return;
}
stack.push(new Integer[]{val, Math.min(val, stack.peek()[1])});
}
public void pop() {
stack.pop();
}
public int top() {
return stack.peek()[0];
}
public int getMin() {
return stack.peek()[1];
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
1038. 从二叉搜索树到更大和树【再探 BST】
前置:BST的中序遍历为:顺序排序
注意:此前一直用的是:左 中 右
那么变换下思维:右 中 左 的话,就成为了 逆序排序
BST最右侧为最大值
我们的 sum 记录的是比当前大的和
class Solution {
// BST中序是按照顺序的
// 树中所有值都不重复
// 左小右大 ===> 右侧都是比当前大的
int sum = 0;
public TreeNode bstToGst(TreeNode root) {
inOrder(root);
return root;
}
public void inOrder(TreeNode node){
if (node == null){
return;
}
inOrder(node.right);
node.val += sum;
sum = node.val; // 更新 sum
inOrder(node.left);
}
}
437. 路径总和Ⅲ【3次递归】
class Solution {
int res = 0;
public int pathSum(TreeNode root, int targetSum) {
inOrder(root, targetSum);
return res;
}
public void inOrder(TreeNode node, int targetSum){
if (node == null){
return;
}
getResult(node, targetSum, node.val); // 遍历每一个数组
inOrder(node.left, targetSum);
inOrder(node.right, targetSum);
}
public void getResult(TreeNode node, int targetSum, long val){
if (val == targetSum){
res++;
}
if (node.left != null) {
getResult(node.left, targetSum, val + node.left.val);
}
if (node.right != null) {
getResult(node.right, targetSum, val + node.right.val);
}
}
}
124. 二叉树中的最大路径和【⭐】
class Solution {
int res = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
suffixOrder(root);
return res;
}
public int suffixOrder(TreeNode node){
if (node == null){
return 0;
}
int leftVal = suffixOrder(node.left);
int rightVal = suffixOrder(node.right);
res = Math.max(res, node.val + leftVal + rightVal);
return Math.max(Math.max(leftVal, rightVal) + node.val, 0); // 如果负收益的话,就舍弃,即:取 0
}
}