数组
核心思想
- 数组是一种线性数据结构,存储一组相同类型的元素,支持随机访问。
- 时间复杂度:
- 访问:O(1)
- 插入/删除:O(n)(需要移动元素)
- 空间复杂度:O(n)
图示描述
- 绘制一个水平排列的矩形块,每个矩形块表示数组的一个元素。
- 在每个矩形块中写上对应的值。
- 示例:数组
[3, 1, 4, 1, 5]
的图示如下:
+---+---+---+---+---+
| 3 | 1 | 4 | 1 | 5 |
+---+---+---+---+---+
代码实现
int[] arr = new int[5];
arr[0] = 10;
arr[1] = 20;
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
面试案例
- 问题:给定一个数组
[3, 1, 4, 1, 5, 9]
,找到其中的最大值。 - 答案:返回
9
。
链表
核心思想
- 链表由节点组成,每个节点包含数据和指向下一个节点的指针。
- 时间复杂度:
- 访问:O(n)
- 插入/删除:O(1)(已知节点位置时)
图示描述
- 每个节点用一个圆圈表示,圆圈内写上节点的值。
- 用箭头连接每个节点,表示指向下一个节点的关系。
- 示例:链表
[1 -> 2 -> 3 -> 4 -> 5]
的图示如下:
(1) -> (2) -> (3) -> (4) -> (5) -> null
代码实现
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
this.next = null;
}
}
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
面试案例
- 问题:反转链表
[1 -> 2 -> 3 -> 4 -> 5]
。 - 答案:返回
[5 -> 4 -> 3 -> 2 -> 1]
。
队列
核心思想
- 队列是一种先进先出(FIFO)的数据结构,常用于任务调度、广度优先搜索等场景。
- 时间复杂度:
图示描述
- 使用一个水平排列的矩形块表示队列。
- 左边是队首,右边是队尾。
- 示例:队列
[A, B, C]
的图示如下:
Front --> [A] [B] [C] <-- Rear
代码实现
import java.util.LinkedList;
import java.util.Queue;
Queue<Integer> queue = new LinkedList<>();
queue.offer(1);
queue.offer(2);
int front = queue.poll();
System.out.println(front);
面试案例
- 问题:使用队列实现一个简单的任务调度系统。
- 答案:通过
offer
和 poll
模拟任务的添加和处理。
栈
核心思想
- 栈是一种后进先出(LIFO)的数据结构,常用于括号匹配、表达式求值等场景。
- 时间复杂度:
图示描述
- 使用垂直排列的矩形块表示栈。
- 最上面的矩形块是栈顶,最下面是栈底。
- 示例:栈
[1, 2, 3]
的图示如下:
Top -->
+---+
| 3 |
+---+
| 2 |
+---+
| 1 |
+---+
Bottom
代码实现
import java.util.Stack;
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.push(2);
int top = stack.pop();
System.out.println(top);
面试案例
- 问题:检查字符串
"([{}])"
是否合法。 - 答案:返回
true
。
堆
核心思想
- 堆是一种完全二叉树,分为最大堆和最小堆,常用于优先队列、Top K 问题。
- 时间复杂度:
- 插入/删除:O(log n)
- 获取堆顶元素:O(1)
图示描述
- 使用一棵完全二叉树表示堆。
- 对于最大堆,父节点的值大于等于子节点的值;对于最小堆,父节点的值小于等于子节点的值。
- 示例:最大堆
[9, 5, 8, 1, 4]
的图示如下:
(9)
/ \
(5) (8)
/ \
(1) (4)
代码实现
import java.util.PriorityQueue;
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
minHeap.offer(3);
minHeap.offer(1);
minHeap.offer(4);
int min = minHeap.poll();
System.out.println(min);
面试案例
- 问题:找出数组
[3, 1, 4, 1, 5, 9]
中最大的两个数。 - 答案:返回
[9, 5]
。
散列表
核心思想
- 散列表通过哈希函数将键映射到值,支持快速查找、插入和删除。
- 时间复杂度:
- 查找/插入/删除:O(1)(平均),O(n)(最坏)
图示描述
- 使用多个桶(数组)表示散列表。
- 每个桶可以存储一个链表或其他数据结构来解决哈希冲突。
- 示例:散列表
{"Alice": 25, "Bob": 30}
的图示如下:
Bucket 0: []
Bucket 1: ["Alice" -> 25]
Bucket 2: ["Bob" -> 30]
Bucket 3: []
代码实现
import java.util.HashMap;
HashMap<String, Integer> map = new HashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
int age = map.get("Alice");
System.out.println(age);
面试案例
- 问题:统计字符串
"hello world"
中每个字符的出现次数。 - 答案:返回
{h=1, e=1, l=3, o=2, w=1, r=1, d=1}
。
树
核心思想
- 树是一种非线性数据结构,由节点和边组成,具有层次结构。
- 时间复杂度:
图示描述
- 使用节点和边表示树。
- 每个节点用一个圆圈表示,圆圈内写上节点的值。
- 用箭头或线段连接节点,表示父子关系。
- 示例:树
[1 -> [2, 3], 2 -> [4, 5]]
的图示如下:
(1)
/ \
(2) (3)
/ \
(4) (5)
代码实现
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
this.left = null;
this.right = null;
}
}
public void preOrder(TreeNode root) {
if (root == null) return;
System.out.println(root.val);
preOrder(root.left);
preOrder(root.right);
}
面试案例
- 问题:对二叉树进行前序遍历。
- 答案:输出节点值的顺序。
二叉树
核心思想
- 二叉树是每个节点最多有两个子节点的树,常用于搜索和排序。
- 时间复杂度:
图示描述
- 类似于普通树,但每个节点最多有两个子节点(左子节点和右子节点)。
- 示例:二叉树
[1 -> [2, 3], 2 -> [4, 5]]
的图示如下:
(1)
/ \
(2) (3)
/ \
(4) (5)
代码实现
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> 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;
}
面试案例
- 问题:对二叉树进行层次遍历。
- 答案:返回每层节点值的列表。
平衡二叉树
核心思想
- 平衡二叉树是一种特殊的二叉搜索树,任意节点的左右子树高度差不超过 1。
- 时间复杂度:
图示描述
- 类似于二叉树,但需要满足平衡条件(任意节点的左右子树高度差不超过 1)。
- 示例:平衡二叉树
[10 -> [5, 20], 5 -> [3, 7], 20 -> [15, 25]]
的图示如下:
(10)
/ \
(5) (20)
/ \ / \
(3) (7) (15) (25)
代码实现
class AVLTree {
class Node {
int val, height;
Node left, right;
Node(int val) {
this.val = val;
this.height = 1;
}
}
private int height(Node node) {
return node == null ? 0 : node.height;
}
private Node rotateRight(Node y) {
Node x = y.left;
Node T2 = x.right;
x.right = y;
y.left = T2;
y.height = Math.max(height(y.left), height(y.right)) + 1;
x.height = Math.max(height(x.left), height(x.right)) + 1;
return x;
}
private Node rotateLeft(Node x) {
Node y = x.right;
Node T2 = y.left;
y.left = x;
x.right = T2;
x.height = Math.max(height(x.left), height(x.right)) + 1;
y.height = Math.max(height(y.left), height(y.right)) + 1;
return y;
}
public Node insert(Node node, int val) {
if (node == null) return new Node(val);
if (val < node.val) {
node.left = insert(node.left, val);
} else if (val > node.val) {
node.right = insert(node.right, val);
} else {
return node;
}
node.height = 1 + Math.max(height(node.left), height(node.right));
int balance = getBalance(node);
if (balance > 1 && val < node.left.val) return rotateRight(node);
if (balance < -1 && val > node.right.val) return rotateLeft(node);
if (balance > 1 && val > node.left.val) {
node.left = rotateLeft(node.left);
return rotateRight(node);
}
if (balance < -1 && val < node.right.val) {
node.right = rotateRight(node.right);
return rotateLeft(node);
}
return node;
}
private int getBalance(Node node) {
return node == null ? 0 : height(node.left) - height(node.right);
}
}
面试案例
- 问题:插入元素
[10, 20, 30, 40, 50, 25]
构建平衡二叉树。 - 答案:返回平衡后的树结构。