java
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class BinaryTreeDepth {
public static int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth, rightDepth) + 1;
}
public static void main(String[] args) {
TreeNode root = new TreeNode(3);
root.left = new TreeNode(9);
root.right = new TreeNode(20);
root.right.left = new TreeNode(15);
root.right.right = new TreeNode(7);
System.out.println(maxDepth(root));
}
}
二叉树的深度是指从根节点到最远叶子节点的最长路径上的节点数。此方法采用递归的方式计算,对于二叉树的每个节点,其深度等于左右子树深度的最大值加 1,当节点为空时,深度为 0。
java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class BinaryTreeTraversal {
// 前序遍历
public static List preorderTraversal(TreeNode root) {
List result = new ArrayList<>();
preorder(root, result);
return result;
}
private static void preorder(TreeNode root, List result) {
if (root == null) {
return;
}
result.add(root.val);
preorder(root.left, result);
preorder(root.right, result);
}
// 中序遍历
public static List inorderTraversal(TreeNode root) {
List result = new ArrayList<>();
inorder(root, result);
return result;
}
private static void inorder(TreeNode root, List result) {
if (root == null) {
return;
}
inorder(root.left, result);
result.add(root.val);
inorder(root.right, result);
}
// 后序遍历
public static List postorderTraversal(TreeNode root) {
List result = new ArrayList<>();
postorder(root, result);
return result;
}
private static void postorder(TreeNode root, List result) {
if (root == null) {
return;
}
postorder(root.left, result);
postorder(root.right, result);
result.add(root.val);
}
// 层序遍历
public static List> levelOrder(TreeNode root) {
List> result = new ArrayList<>();
if (root == null) {
return result;
}
Queue queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
List level = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
level.add(node.val);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
result.add(level);
}
return result;
}
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
System.out.println("前序遍历: " + preorderTraversal(root));
System.out.println("中序遍历: " + inorderTraversal(root));
System.out.println("后序遍历: " + postorderTraversal(root));
System.out.println("层序遍历: " + levelOrder(root));
}
}
java
import java.util.ArrayList;
import java.util.List;
public class PrimeFactorization {
public static List primeFactorize(int n) {
List factors = new ArrayList<>();
for (int i = 2; i * i <= n; i++) {
while (n % i == 0) {
factors.add(i);
n /= i;
}
}
if (n > 1) {
factors.add(n);
}
return factors;
}
public static void main(String[] args) {
int num = 90;
List factors = primeFactorize(num);
StringBuilder result = new StringBuilder(num + " = ");
for (int i = 0; i < factors.size(); i++) {
result.append(factors.get(i));
if (i < factors.size() - 1) {
result.append(" * ");
}
}
System.out.println(result);
}
}
整数分解质因数是将一个大于 1 的整数表示为若干个质数的乘积的形式。该方法从最小的质数 2 开始,不断尝试将该数分解,如果能整除则将该质数加入结果列表,并将原数除以该质数,直到不能整除为止,然后尝试下一个质数,直到原数变为 1 或者无法再分解。
java
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class NonRecursivePostorderTraversal {
public static List postorderTraversal(TreeNode root) {
List result = new ArrayList<>();
if (root == null) {
return result;
}
Stack stack1 = new Stack<>();
Stack stack2 = new Stack<>();
stack1.push(root);
while (!stack1.isEmpty()) {
TreeNode node = stack1.pop();
stack2.push(node);
if (node.left != null) {
stack1.push(node.left);
}
if (node.right != null) {
stack1.push(node.right);
}
}
while (!stack2.isEmpty()) {
result.add(stack2.pop().val);
}
return result;
}
public static void main(String[] args) {
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
System.out.println(postorderTraversal(root));
}
}
二叉树的非递归后续遍历是指不使用递归的方式,按照左子树、右子树、根节点的顺序遍历二叉树。该方法使用两个栈来模拟递归过程,首先将根节点压入栈 1,然后从栈 1 弹出节点并压入栈 2,同时将该节点的左右子节点压入栈 1,最后从栈 2 弹出节点并输出。
java
class PrintABC {
private int state = 0;
private final Object lock = new Object();
public void printA() {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
while (state % 3 != 0) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.print("A");
state++;
lock.notifyAll();
}
}
}
public void printB() {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
while (state % 3 != 1) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.print("B");
state++;
lock.notifyAll();
}
}
}
public void printC() {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
while (state % 3 != 2) {
try {
lock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
System.out.print("C");
state++;
lock.notifyAll();
}
}
}
}
public class PrintABCThreads {
public static void main(String[] args) {
PrintABC printABC = new PrintABC();
Thread threadA = new Thread(printABC::printA);
Thread threadB = new Thread(printABC::printB);
Thread threadC = new Thread(printABC::printC);
threadA.start();
threadB.start();
threadC.start();
}
}
通过多线程编程实现三个线程轮流打印 ABC 十次,使用一个共享的状态变量 state
来控制线程的执行顺序,利用 synchronized
关键字和 wait()
、notifyAll()
方法来实现线程的同步和通信。每个线程在进入临界区后,检查 state
的值是否满足自己的打印条件,如果不满足则调用 wait()
方法进入等待状态,当满足条件时打印字符并更新 state
的值,然后调用 notifyAll()
方法唤醒其他线程。
synchronized
保证线程安全。wait()
和 notifyAll()
实现线程间的通信和同步。java
import java.util.ArrayList;
import java.util.List;
public class Subsets {
public static List> subsets(int[] nums) {
List> result = new ArrayList<>();
int n = nums.length;
for (int i = 0; i < (1 << n); i++) {
List subset = new ArrayList<>();
for (int j = 0; j < n; j++) {
if ((i & (1 << j)) != 0) {
subset.add(nums[j]);
}
}
result.add(subset);
}
return result;
}
public static void main(String[] args) {
int[] nums = {1, 2, 3};
List> subsets = subsets(nums);
for (List subset : subsets) {
System.out.println(subset);
}
}
}
列举集合的所有子集是指找出给定集合的所有可能的子集。该方法使用位运算来生成集合的所有子集,对于一个包含 n
个元素的集合,它的子集个数为 2n,可以用一个长度为 n
的二进制数来表示每个子集,二进制数的每一位对应集合中的一个元素,如果该位为 1,则表示该元素在子集中,否则不在子集中。
1 << n
用于计算 2n。i & (1 << j)
用于判断第 j
位是否为 1。java
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class SortList {
public static ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode slow = head;
ListNode fast = head;
ListNode prev = null;
while (fast != null && fast.next != null) {
prev = slow;
slow = slow.next;
fast = fast.next.next;
}
prev.next = null;
ListNode left = sortList(head);
ListNode right = sortList(slow);
return merge(left, right);
}
private static ListNode merge(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode current = dummy;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
current.next = l1;
l1 = l1.next;
} else {
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
if (l1 != null) {
current.next = l1;
}
if (l2 != null) {
current.next = l2;
}
return dummy.next;
}
public static void main(String[] args) {
ListNode head = new ListNode(4);
head.next = new ListNode(2);
head.next.next = new ListNode(1);
head.next.next.next = new ListNode(3);
ListNode sortedHead = sortList(head);
while (sortedHead != null) {
System.out.print(sortedHead.val + " ");
sortedHead = sortedHead.next;
}
}
}
使用归并排序的思想对单链表进行排序。首先通过快慢指针将链表分成两部分,然后分别对这两部分进行递归排序,最后将排序好的两部分合并,使得链表中的元素按升序排列,且时间复杂度为 O(nlogn),空间复杂度为 O(1)。
java
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class WordBreak {
public static boolean wordBreak(String s, String[] wordDict) {
Set dict = new HashSet<>(Arrays.asList(wordDict));
boolean[] dp = new boolean[s.length() + 1];
dp[0] = true;
for (int i = 1; i <= s.length(); i++) {
for (int j = 0; j < i; j++) {
if (dp[j] && dict.contains(s.substring(j, i))) {
dp[i] = true;
break;
}
}
}
return dp[s.length()];
}
public static void main(String[] args) {
String s = "leetcode";
String[] wordDict = {"leet", "code"};
System.out.println(wordBreak(s, wordDict));
}
}
使用动态规划的方法判断一个字符串能否被字典中的单词完全分词。定义一个布尔型数组 dp
,dp[i]
表示字符串的前 i
个字符能否被字典中的单词完全分词。对于每个 i
,遍历 0
到 i - 1
的所有 j
,如果 dp[j]
为 true
且 s.substring(j, i)
在字典中,则 dp[i]
为 true
。
dp
的初始化和状态转移方程。java
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class FindNodeInList {
// 找出链表的中间节点
public static ListNode middleNode(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
// 找出链表的第 n/m 个节点
public static ListNode findNthMNode(ListNode head, int n, int m) {
ListNode p1 = head;
ListNode p2 = head;
int count = 0;
while (p1 != null) {
count++;
p1 = p1.next;
}
int target = count * n / m;
for (int i = 0; i < target; i++) {
p2 = p2.next;
}
return p2;
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);
ListNode middle = middleNode(head);
System.out.println("中间节点的值: " + middle.val);
ListNode nthM = findNthMNode(head, 1, 3);
System.out.println("第 1/3 个节点的值: " + nthM.val);
}
}
n/m
计算目标节点的位置,最后再次遍历链表找到该节点。java
import java.util.ArrayList;
import java.util.List;
public class PascalTriangle {
public static List> generate(int numRows) {
List> triangle = new ArrayList<>();
if (numRows == 0) {
return triangle;
}
for (int i = 0; i < numRows; i++) {
List row = new ArrayList<>();
for (int j = 0; j <= i; j++) {
if (j == 0 || j == i) {
row.add(1);
} else {
List prevRow = triangle.get(i - 1);
row.add(prevRow.get(j - 1) + prevRow.get(j));
}
}
triangle.add(row);
}
return triangle;
}
public static void main(String[] args) {
int numRows = 5;
List> triangle = generate(numRows);
for (List row : triangle) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
}
}
杨辉三角是一个由数字排列成的三角形数阵,其特点是每个数等于它上方两数之和,每行的首尾数字都是 1。该方法使用两层循环,外层循环控制行数,内层循环控制每行的元素个数,根据上述规则生成杨辉三角。
友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读
https://download.csdn.net/download/ylfhpy/90541638