面试准备——Java数据结构【理论基础,高级程序员必备】

数组

核心思想

  • 数组是一种线性数据结构,存储一组相同类型的元素,支持随机访问。
  • 时间复杂度:
    • 访问:O(1)
    • 插入/删除:O(n)(需要移动元素)
  • 空间复杂度:O(n)

图示描述

  • 绘制一个水平排列的矩形块,每个矩形块表示数组的一个元素。
  • 在每个矩形块中写上对应的值。
  • 示例:数组 [3, 1, 4, 1, 5] 的图示如下:
+---+---+---+---+---+
| 3 | 1 | 4 | 1 | 5 |
+---+---+---+---+---+

代码实现

// 初始化数组
int[] arr = new int[5]; // 长度为 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)的数据结构,常用于任务调度、广度优先搜索等场景。
  • 时间复杂度:
    • 入队/出队:O(1)

图示描述

  • 使用一个水平排列的矩形块表示队列。
  • 左边是队首,右边是队尾。
  • 示例:队列 [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); // 输出 1

面试案例

  • 问题:使用队列实现一个简单的任务调度系统。
  • 答案:通过 offerpoll 模拟任务的添加和处理。

核心思想

  • 栈是一种后进先出(LIFO)的数据结构,常用于括号匹配、表达式求值等场景。
  • 时间复杂度:
    • 入栈/出栈:O(1)

图示描述

  • 使用垂直排列的矩形块表示栈。
  • 最上面的矩形块是栈顶,最下面是栈底。
  • 示例:栈 [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); // 输出 2

面试案例

  • 问题:检查字符串 "([{}])" 是否合法。
  • 答案:返回 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); // 输出 1

面试案例

  • 问题:找出数组 [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"); // 返回 25
System.out.println(age);

面试案例

  • 问题:统计字符串 "hello world" 中每个字符的出现次数。
  • 答案:返回 {h=1, e=1, l=3, o=2, w=1, r=1, d=1}

核心思想

  • 树是一种非线性数据结构,由节点和边组成,具有层次结构。
  • 时间复杂度:
    • 遍历:O(n)

图示描述

  • 使用节点和边表示树。
  • 每个节点用一个圆圈表示,圆圈内写上节点的值。
  • 用箭头或线段连接节点,表示父子关系。
  • 示例:树 [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);
}

面试案例

  • 问题:对二叉树进行前序遍历。
  • 答案:输出节点值的顺序。

二叉树

核心思想

  • 二叉树是每个节点最多有两个子节点的树,常用于搜索和排序。
  • 时间复杂度:
    • 遍历:O(n)

图示描述

  • 类似于普通树,但每个节点最多有两个子节点(左子节点和右子节点)。
  • 示例:二叉树 [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。
  • 时间复杂度:
    • 插入/删除/查找:O(log n)

图示描述

  • 类似于二叉树,但需要满足平衡条件(任意节点的左右子树高度差不超过 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] 构建平衡二叉树。
  • 答案:返回平衡后的树结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值