Appearance
手写单例模式(双重检查锁定)。
java
public class Demo {
private static Demo d;
private Demo() {}
public static Demo getDemo() {
if (d == null) {
synchronized (Demo.class) {
if (d == null) {
d = new Demo();
}
}
}
return d;
}
}SQL题: 给定 orders (id, user_id, amount) 和 users (id, name),查询每个用户的订单总数和总金额。
sql
SELECT
u.id AS user_id,
u.name AS user_name,
COUNT(o.id) AS order_count,
SUM(o.amount) AS total_amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name
ORDER BY total_amount DESC;二叉树的中序遍历。(递归和非递归都要会)。
递归
java
import java.util.ArrayList;
import java.util.List;
// 二叉树节点定义
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class BinaryTreeInorderTraversal {
/**
* 递归实现中序遍历
* 遍历顺序:左子树 -> 根节点 -> 右子树
*/
public List<Integer> inorderTraversalRecursive(TreeNode root) {
List<Integer> result = new ArrayList<>();
inorderHelper(root, result);
return result;
}
private void inorderHelper(TreeNode node, List<Integer> result) {
if (node == null) {
return;
}
// 1. 遍历左子树
inorderHelper(node.left, result);
// 2. 访问根节点
result.add(node.val);
// 3. 遍历右子树
inorderHelper(node.right, result);
}
}非递归
java
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class BinaryTreeInorderTraversal {
/**
* 非递归实现中序遍历(使用栈)
* 思路:
* 1. 从根节点开始,将所有左子节点入栈
* 2. 弹出栈顶元素并访问
* 3. 如果有右子树,对右子树重复步骤1
*/
public List<Integer> inorderTraversalIterative(TreeNode root) {
List<Integer> result = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode current = root;
while (current != null || !stack.isEmpty()) {
// 将当前节点及其所有左子节点入栈
while (current != null) {
stack.push(current);
current = current.left;
}
// 弹出栈顶节点并访问
current = stack.pop();
result.add(current.val);
// 转向右子树
current = current.right;
}
return result;
}
}反转链表。
java
// 链表节点类
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public class ReverseLinkedList {
/**
* 迭代法反转链表
* 思路:使用三个指针,逐个反转节点指向
* 时间复杂度:O(n),空间复杂度:O(1)
*/
public ListNode reverseListIterative(ListNode head) {
ListNode prev = null; // 前一个节点
ListNode current = head; // 当前节点
while (current != null) {
ListNode nextTemp = current.next; // 保存下一个节点
current.next = prev; // 反转指针
prev = current; // 移动prev
current = nextTemp; // 移动current
}
return prev; // 返回新的头节点
}
}有效的括号。(使用栈)。
java
import java.util.Stack;
import java.util.HashMap;
import java.util.Map;
public class ValidParentheses {
/**
* 另一种实现方式,不使用哈希表
*/
public boolean isValid2(String s) {
if (s.length() % 2 != 0) {
return false;
}
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(' || c == '{' || c == '[') {
stack.push(c);
} else {
if (stack.isEmpty()) {
return false;
}
char top = stack.pop();
if ((c == ')' && top != '(') ||
(c == '}' && top != '{') ||
(c == ']' && top != '[')) {
return false;
}
}
}
return stack.isEmpty();
}
/**
* 测试方法
*/
public static void main(String[] args) {
ValidParentheses solution = new ValidParentheses();
// 测试用例
String[] testCases = {
"()", // true
"()[]{}", // true
"(]", // false
"([)]", // false
"{[]}", // true
"]", // false
"", // true
"((()))", // true
"([{}])", // true
"(((" // false
};
boolean[] expected = {
true, true, false, false, true, false, true, true, true, false
};
System.out.println("测试结果:");
System.out.println("字符串\t\t预期\t实际\t结果");
System.out.println("----------------------------------------");
for (int i = 0; i < testCases.length; i++) {
boolean result = solution.isValid(testCases[i]);
String status = result == expected[i] ? "✓" : "✗";
System.out.printf("%-10s\t%-5s\t%-5s\t%s\n",
testCases[i], expected[i], result, status);
}
}
}快速排序 或 归并排序。
两个线程交替打印1-100。(考察 wait()/notify() 或 Lock/Condition)。
合并两个有序数组。
java
public class MergeSortedArray {
/**
* 使用额外空间合并两个有序数组
* 时间复杂度:O(m+n)
* 空间复杂度:O(m+n)
*/
public void mergeWithExtraSpace(int[] nums1, int m, int[] nums2, int n) {
int[] result = new int[m + n];
int i = 0, j = 0, k = 0;
// 合并两个有序数组
while (i < m && j < n) {
if (nums1[i] <= nums2[j]) {
result[k++] = nums1[i++];
} else {
result[k++] = nums2[j++];
}
}
// 处理剩余元素
while (i < m) {
result[k++] = nums1[i++];
}
while (j < n) {
result[k++] = nums2[j++];
}
// 将结果复制回 nums1
System.arraycopy(result, 0, nums1, 0, m + n);
}
}