目录
4.1 题目:leetcode第700题:二叉搜索树中的搜索
1. 背景与目的:方便排查问题
在leetcode刷题中,当出现链表题或者二叉树的题目的时候
给出的输入和输出示例通常是数组形式, 如图所示:
这样很不清晰,不知道自己返回的结构到底是怎么样的,如果能够打印出合适的格式,会方便我们排查问题。
leetcode给出的输入与输出示例都不太直观:
如下先给出两种数据结构题型的示例:
链表结构:

二叉树结构:
2. 效果
我们首先给出工具的效果:
给出的示例比较简单:
下文给出更详细的示例。

3. 工具类代码
首先创建一个包: definition, 用于定义链表节点和树节点:
如何定义都和leetcode上面保持一致,可以放心导入。
3.1 链表数据结构定义
package definition;
/**
* @author: Rehse
* @description: 定义链表结构
* @time: 2025/7/27 12:08
*/
public class ListNode {
public int val;
public ListNode next;
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
3.2 二叉树数据结构定义
package definition;
/**
* @author: Rehse
* @description: 定义二叉树结构
* @time: 2025/7/27 12:08
*/
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
TreeNode() {
}
public TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
3.3 工具类代码
这个工具类定义在预先定义的工具类包utils下面,不需要的话就删掉,或者改喜欢的名字。
工具类下面有main函数, 可以打印出示例康康。
package utils;
// 导入链表和二叉树数据结构类
import definition.ListNode;
import definition.TreeNode;
import java.util.*;
/**
* @author: Rehse
* @description: 打印工具类
* @time: 2025/7/27 12:10
*/
public class PrintUtils {
/**
* 根据传入数组参数 构建链表
*/
public ListNode listNode;
public TreeNode treeNode;
/**
* 有时候 leetcode给出的示例的某个null值, 这里用Integer的最小值来代替null节点
*/
static final int NULL = Integer.MIN_VALUE;
/**
* 节点类型: 0->链表, 1->树
*/
public static int type;
/**
* 节点类型: 链表
*/
public static final int NODE_TYPE_LINKED = 0;
/**
* 节点类型: 树
*/
public static final int NODE_TYPE_TREE = 1;
/**
* 空节点用字符串"null"表示
*/
private static final String NULL_SYMBOL = "null";
/**
* @return ListNode
* @author: Rehse
* @description: 返回链表结构
* @time: 2025/7/27 11:50
*/
public ListNode getListNode() {
return this.listNode;
}
/**
* @return ListNode
* @author: Rehse
* @description: 返回二叉树结构
* @time: 2025/7/27 11:50
*/
public TreeNode getTreeNode() {
return this.treeNode;
}
/**
* @return void
* @author: Rehse
* @description: 构造函数: 根据传入的数组和类型(0: 链表, 还是1: 树)构造工具类
* @param[1] nums
* @param[2] type
* @time: 2025/7/27 10:25
*/
public PrintUtils(int[] nums, int type) {
this.type = type;
if (type == NODE_TYPE_LINKED) {
listNode = new ListNode(nums[0]);
ListNode cur = listNode;
for (int i = 1; i < nums.length; i++) {
cur.next = new ListNode(nums[i]);
cur = cur.next;
}
cur.next = null;
} else if (type == NODE_TYPE_TREE) {
Queue<TreeNode> queue = new ArrayDeque<>();
treeNode = new TreeNode(nums[0]);
queue.offer(treeNode);
for (int index = 1; index < nums.length; index++) {
TreeNode node = queue.poll();
if (index < nums.length && nums[index] != NULL) {
node.left = new TreeNode(nums[index]);
queue.offer(node.left);
}
index++;
// 右子节点
if (index < nums.length && nums[index] != NULL) {
node.right = new TreeNode(nums[index]);
queue.offer(node.right);
}
}
} else {
throw new IllegalArgumentException("非法的type参数,必须是0(链表)或1(树)");
}
}
/**
* @return void
* @author: Rehse
* @description: 自动根据类型打印链表或者树
* @time: 2025/7/27 10:16
*/
public void print() {
if (type == NODE_TYPE_LINKED) {
printListNode(listNode);
} else {
printTree(treeNode);
}
}
/**
* @return void
* @author: Rehse
* @description: 打印链表
* @param[1] head
* @time: 2025/7/27 10:16
*/
public static void printListNode(ListNode head) {
System.out.println("打印链表:");
ListNode cur = head;
while (cur != null) {
System.out.print(cur.val + "->");
cur = cur.next;
}
System.out.print("null\n");
System.out.println("-----------------------------------------------------------------------------------------");
}
/**
* @return void
* @author: Rehse
* @description: 打印树 分层地打印出来 可打印出空节点
* @param[1] root
* @time: 2025/7/27 10:16
*/
public static void printTree(TreeNode root) {
System.out.println("打印树:");
if (root == null) {
System.out.println("树为空");
return;
}
int height = getHeight(root);
int maxValLength = getMaxValueLength(root);
int spaceWidth = maxValLength + 2; // 每个节点的显示宽度
List<List<String>> levels = new ArrayList<>();
buildLevels(root, height, maxValLength, levels);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < levels.size(); i++) {
List<String> level = levels.get(i);
int leadingSpace = (int) (spaceWidth * Math.pow(2, height - i - 1) - spaceWidth / 2);
sb.append(" ".repeat(leadingSpace));
for (String node : level) {
sb.append(node).append(" ".repeat(spaceWidth * (int) Math.pow(2, height - i) - spaceWidth));
}
sb.append("\n");
}
System.out.print(sb);
System.out.println("-----------------------------------------------------------------------------------------");
}
/**
* @return void
* @author: Rehse
* @description: 构建树层
* @param[1] node
* @param[2] height
* @param[3] maxLen
* @param[4] levels
* @time: 2025/7/27 11:19
*/
private static void buildLevels(TreeNode node, int height, int maxLen, List<List<String>> levels) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(node);
for (int i = 0; i < height; i++) {
int levelSize = queue.size();
List<String> currentLevel = new ArrayList<>();
for (int j = 0; j < levelSize; j++) {
TreeNode curr = queue.poll();
if (curr == null) {
currentLevel.add(String.format("%" + maxLen + "s", NULL_SYMBOL));
queue.offer(null);
queue.offer(null);
} else {
currentLevel.add(String.format("%" + maxLen + "d", curr.val));
queue.offer(curr.left);
queue.offer(curr.right);
}
}
levels.add(currentLevel);
}
}
/**
* @return int
* @author: Rehse
* @description: 获取树的高度
* @param[1] root
* @time: 2025/7/27 11:19
*/
private static int getHeight(TreeNode root) {
if (root == null) return 0;
return 1 + Math.max(getHeight(root.left), getHeight(root.right));
}
/**
* @return int
* @author: Rehse
* @description: 获取最大数值的长度
* @param[1] root
* @time: 2025/7/27 11:19
*/
private static int getMaxValueLength(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int maxLength = 0;
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node != null) {
// 计算当前节点值的字符串长度(考虑负数)
int currentLength = String.valueOf(node.val).length();
maxLength = Math.max(maxLength, currentLength);
queue.offer(node.left);
queue.offer(node.right);
}
}
return maxLength;
}
/**
* @return void
* @author: Rehse
* @description: 获取节点并打印
* @time: 2025/7/27 12:39
*/
public void getAndPrint() {
if (type == NODE_TYPE_LINKED) {
ListNode listNode = this.getListNode();
} else {
TreeNode treeNode = this.getTreeNode();
}
this.print();
}
/**
* @author: Rehse
* @description: 使用示例
* @param[1] args
* @time: 2025/7/27 10:14
*/
public static void main(String[] args) {
PrintUtils utils1 = new PrintUtils(new int[]{1, 2, 3, 4, 5}, 0);
utils1.print();
PrintUtils utils2 = new PrintUtils(new int[]{1, 2, 3, 4, 5}, 1);
utils2.print();
PrintUtils utils3 = new PrintUtils(new int[]{1, 2, 3, 4, NULL, 5}, 1);
utils3.print();
PrintUtils utils4 = new PrintUtils(new int[]{1, 2, 3, 4, NULL, 5, 6, 7, 8, 9}, 1);
utils4.print();
PrintUtils utils5 = new PrintUtils(new int[]{1, 2, 3, 4, NULL, 5, 6, 7, 8, 9}, 2);
utils5.print();
}
}
3.3.1 注意事项
如上代码块中的main函数,
先通过一个数组以及一个type参数(0代表链表,1代表二叉树)构造工具类。
然后调用工具类对象的print()方法即可
注:在leetcode有些二叉树的题在给出的输入示例总是会出现空节点, 用null来表示的
在工具类代码中用一个静态常量NULL来作为替代,
这个NULL值为Integer.MIN_VALUE,
在构造工具类前可以预先定义一下:
static final int NULL = Integer.MIN_VALUE;
在控制台中的效果如下:
type只能是0(链表)或者1(二叉树), 否则抛出异常

4. 使用示例
我在做题的时候一般是这样用的:
4.1 题目:leetcode第700题:二叉搜索树中的搜索
4.1.1 题目介绍
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
示例 1:

输入:root = [4,2,7,1,3], val = 2 输出:[2,1,3]
4.1.2 代码
在main函数里面调用这道题中的函数的时候 先将函数返回类型前面加上static字段。
完整代码如下:
package leetcode.tree;
import definition.TreeNode;
import utils.PrintUtils;
/**
* @author: Rehse
* @description: 二叉搜索树中的搜索
* @date: 2025/7/27
*/
public class Leetcode_700_SearchInABinarySearchTree {
/**
* @author: Rehse
* @description: 递归
* @param[1] root
* @param[2] val
* @return TreeNode
* @time: 2025/7/27 12:17
*/
public static TreeNode searchBST(TreeNode root, int val) {
if (root == null) {
return null;
}
if (val == root.val) {
return root;
}
return searchBST(val < root.val ? root.left : root.right, val);
}
public static void main(String[] args) {
// 1.可以根据数组构造工具类 第二个参数为1 代表这是树结构
PrintUtils utils = new PrintUtils(new int[]{4, 2, 7, 1, 3}, 1);
// 2.通过工具类返回这个二叉树的结构
TreeNode root = utils.getTreeNode();
// 3.通过工具类对象可以打印出来本题示例看看 这个print()则是根据节点类型type自动调用第5条的打印树的函数
utils.print();
// 第2步和第3步 可以只用下面这个函数 合并了两个操作 得到并打印
// utils.getAndPrint();
// 4.调用本题函数 返回一个结果树
TreeNode resultTree = searchBST(root, 2);
// 5.通过工具类的静态函数.打印树, 打印出这个结果树的结构
PrintUtils.printTree(resultTree);
}
}
4.1.3 控制台
这道题有点简单,返回的结果子树也比较简单,读者可以用更复杂的题试试。

4.2 题目:leetcode第148题:排序链表
4.2.1 题目介绍
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
示例 :

输入:head = [-1,5,3,4,0] 输出:[-1,0,3,4,5]
4.2.2 代码
在main函数里面调用这道题中的函数的时候 先将函数返回类型前面加上static字段。
完整代码如下:
package leetcode.linkedlist;
import definition.ListNode;
import utils.PrintUtils;
/**
* @author: Rehse
* @description: 排序链表
* @date: 2025/7/27
*/
public class Leetcode_148_SortList {
public static ListNode sortList(ListNode head) {
return sortList(head, null);
}
public static ListNode sortList(ListNode head, ListNode tail) {
if (head == null) {
return head;
}
if (head.next == tail) {
head.next = null;
return head;
}
ListNode slow = head, fast = head;
while (fast != tail) {
slow = slow.next;
fast = fast.next;
if (fast != tail) {
fast = fast.next;
}
}
ListNode mid = slow;
ListNode list1 = sortList(head, mid);
ListNode list2 = sortList(mid, tail);
ListNode sorted = merge(list1, list2);
return sorted;
}
public static ListNode merge(ListNode head1, ListNode head2) {
ListNode dummyHead = new ListNode(0);
ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
while (temp1 != null && temp2 != null) {
if (temp1.val <= temp2.val) {
temp.next = temp1;
temp1 = temp1.next;
} else {
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if (temp1 != null) {
temp.next = temp1;
} else if (temp2 != null) {
temp.next = temp2;
}
return dummyHead.next;
}
public static void main(String[] args) {
// 1.可以根据数组构造工具类 第二个参数为0 代表这是链表结构
PrintUtils utils = new PrintUtils(new int[]{-1,5,3,4,0}, 0);
// 2.通过工具类返回这个二叉树的结构
ListNode head = utils.getListNode();
// 3.通过工具类对象可以打印出来本题示例看看 这个print()则是根据节点类型type自动调用第5条的打印树的函数
utils.print();
// 第2步和第3步 可以只用下面这个函数 合并了两个操作 得到并打印
// utils.getAndPrint();
// 4.调用本题函数 返回一个链表
ListNode result = sortList(head);
// 5.通过工具类的静态函数.打印链表, 打印出这个结果链表的结构
PrintUtils.printListNode(result);
}
}
4.2.3 控制台

屎山代码仅供参考,觉得我拉的屎有用的话,点个赞么么哒!

1119

被折叠的 条评论
为什么被折叠?



