目录
在大厂的技术面试中,手撕代码环节常常涉及各种数据结构的运用。本文将对常见的数据结构进行汇总,并结合 Java 代码示例进行讲解,帮助大家更好地应对大厂面试。
一、数组与 ArrayList
(一)概念
- 数组:是一组具有相同类型的元素的集合,在内存中连续存储。
- ArrayList:是 Java 中的一种动态数组实现,它可以自动调整大小以适应存储的元素数量。
(二)常见操作及代码示例
- 遍历数组或 ArrayList
// 遍历数组
int[] arr = {1, 2, 3, 4, 5};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 遍历 ArrayList
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
for (Integer num : list) {
System.out.println(num);
}
- 查找特定元素
// 在数组中查找特定元素
int[] arr = {1, 2, 3, 4, 5};
int target = 3;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
System.out.println("Found at index: " + i);
break;
}
}
// 在 ArrayList 中查找特定元素
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
int target = 3;
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == target) {
System.out.println("Found at index: " + i);
break;
}
}
- ArrayList 的截取与拼接
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
// 截取索引 1 到 3 的元素
ArrayList<Integer> subList = new ArrayList<>(list.subList(1, 4));
// 在 ArrayList 末尾添加元素
list.add(6);
二、链表
(一)概念
链表是一种线性数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
(二)常见操作及代码示例
- 单链表的创建与遍历
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
}
public class LinkedList {
public static ListNode createLinkedList(int[] arr) {
if (arr.length == 0) {
return null;
}
ListNode head = new ListNode(arr[0]);
ListNode current = head;
for (int i = 1; i < arr.length; i++) {
current.next = new ListNode(arr[i]);
current = current.next;
}
return head;
}
public static void traverseLinkedList(ListNode head) {
ListNode current = head;
while (current!= null) {
System.out.println(current.val);
current = current.next;
}
}
}
- 链表的反转
public class LinkedList {
public static ListNode reverseLinkedList(ListNode head) {
ListNode prev = null;
ListNode current = head;
while (current!= null) {
ListNode next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}
}
三、栈与队列
(一)概念
- 栈:是一种后进先出(LIFO)的数据结构。
- 队列:是一种先进先出(FIFO)的数据结构。
(二)常见操作及代码示例
- 用数组实现栈
class Stack {
private int[] stack;
private int top;
Stack(int capacity) {
stack = new int[capacity];
top = -1;
}
public void push(int value) {
if (top == stack.length - 1) {
throw new StackOverflowError();
}
stack[++top] = value;
}
public int pop() {
if (top == -1) {
throw new EmptyStackException();
}
return stack[top--];
}
}
- 用数组实现队列
class Queue {
private int[] queue;
private int front;
private int rear;
private int capacity;
Queue(int capacity) {
queue = new int[capacity];
front = rear = -1;
this.capacity = capacity;
}
public void enqueue(int value) {
if ((rear + 1) % capacity == front) {
throw new IllegalStateException("Queue is full");
}
if (front == -1) {
front = 0;
}
rear = (rear + 1) % capacity;
queue[rear] = value;
}
public int dequeue() {
if (front == -1) {
throw new IllegalStateException("Queue is empty");
}
int value = queue[front];
if (front == rear) {
front = rear = -1;
} else {
front = (front + 1) % capacity;
}
return value;
}
}
四、树
(一)概念
树是一种非线性数据结构,由节点和边组成。每个节点可以有多个子节点。
(二)常见操作及代码示例
- 二叉树的创建与遍历
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
public class BinaryTree {
public static TreeNode createBinaryTree(int[] arr) {
if (arr.length == 0) {
return null;
}
TreeNode[] nodes = new TreeNode[arr.length];
for (int i = 0; i < arr.length; i++) {
if (arr[i]!= -1) {
nodes[i] = new TreeNode(arr[i]);
}
}
for (int i = 0; i < arr.length; i++) {
if (nodes[i]!= null) {
if (2 * i + 1 < arr.length && nodes[2 * i + 1]!= null) {
nodes[i].left = nodes[2 * i + 1];
}
if (2 * i + 2 < arr.length && nodes[2 * i + 2]!= null) {
nodes[i].right = nodes[2 * i + 2];
}
}
}
return nodes[0];
}
public static void preorderTraversal(TreeNode root) {
if (root == null) {
return;
}
System.out.println(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
}
}
- 二叉搜索树的查找与插入
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
public class BinarySearchTree {
public static TreeNode searchBST(TreeNode root, int val) {
if (root == null || root.val == val) {
return root;
}
if (val < root.val) {
return searchBST(root.left, val);
} else {
return searchBST(root.right, val);
}
}
public static TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) {
return new TreeNode(val);
}
if (val < root.val) {
root.left = insertIntoBST(root.left, val);
} else {
root.right = insertIntoBST(root.right, val);
}
return root;
}
}
五、图
(一)概念
图是由一组顶点和一组边组成的数据结构。边可以是有向的或无向的,并且可以有权重。
(二)常见操作及代码示例
- 邻接表表示图
import java.util.ArrayList;
import java.util.List;
class Graph {
int vertices;
List<List<Integer>> adjList;
Graph(int vertices) {
this.vertices = vertices;
adjList = new ArrayList<>();
for (int i = 0; i < vertices; i++) {
adjList.add(new ArrayList<>());
}
}
public void addEdge(int u, int v) {
adjList.get(u).add(v);
adjList.get(v).add(u);
}
}
- 深度优先搜索
class Graph {
int vertices;
List<List<Integer>> adjList;
Graph(int vertices) {
this.vertices = vertices;
adjList = new ArrayList<>();
for (int i = 0; i < vertices; i++) {
adjList.add(new ArrayList<>());
}
}
public void addEdge(int u, int v) {
adjList.get(u).add(v);
adjList.get(v).add(u);
}
public void dfs(int start, boolean[] visited) {
visited[start] = true;
System.out.println(start);
List<Integer> neighbors = adjList.get(start);
for (Integer neighbor : neighbors) {
if (!visited[neighbor]) {
dfs(neighbor, visited);
}
}
}
}
六、哈希表
(一)概念
哈希表是一种根据键(key)直接访问值(value)的数据结构。通过哈希函数将键映射到数组的索引位置。
(二)常见操作及代码示例
- 简单哈希表的实现
import java.util.ArrayList;
import java.util.List;
class HashTable {
private List<Integer>[] table;
private int capacity;
@SuppressWarnings("unchecked")
HashTable(int capacity) {
this.capacity = capacity;
table = new ArrayList[capacity];
for (int i = 0; i < capacity; i++) {
table[i] = new ArrayList<>();
}
}
public void put(int key, int value) {
int index = key % capacity;
List<Integer> list = table[index];
for (int i = 0; i < list.size(); i += 2) {
if (list.get(i) == key) {
list.set(i + 1, value);
return;
}
}
list.add(key);
list.add(value);
}
public int get(int key) {
int index = key % capacity;
List<Integer> list = table[index];
for (int i = 0; i < list.size(); i += 2) {
if (list.get(i) == key) {
return list.get(i + 1);
}
}
return -1;
}
}
在大厂面试中,对于数据结构的考察不仅要求掌握基本的操作,还需要能够灵活运用这些数据结构解决实际问题。通过对这些常见数据结构的学习和练习,大家可以更好地应对大厂面试中的手撕代码环节。