> 技术文档 > Java 高频算法

Java 高频算法


Java高频算法面试题

以下是Java面试中常见的高频算法题目,涵盖了数据结构、算法思想和实际应用场景。

一、数组与字符串

1. 两数之和

public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] { map.get(complement), i }; } map.put(nums[i], i); } throw new IllegalArgumentException(\"No two sum solution\");}

2. 最长无重复字符子串

public int lengthOfLongestSubstring(String s) { Map<Character, Integer> map = new HashMap<>(); int max = 0, left = 0; for (int right = 0; right < s.length(); right++) { char c = s.charAt(right); if (map.containsKey(c)) { left = Math.max(left, map.get(c) + 1); } map.put(c, right); max = Math.max(max, right - left + 1); } return max;}

二、链表操作

3. 反转链表

public ListNode reverseList(ListNode head) { ListNode prev = null; ListNode curr = head; while (curr != null) { ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev;}

4. 合并两个有序链表

public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode dummy = new ListNode(-1); ListNode curr = dummy; while (l1 != null && l2 != null) { if (l1.val < l2.val) { curr.next = l1; l1 = l1.next; } else { curr.next = l2; l2 = l2.next; } curr = curr.next; } curr.next = l1 == null ? l2 : l1; return dummy.next;}

三、树结构

5. 二叉树的最大深度

public int maxDepth(TreeNode root) { if (root == null) return 0; return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;}

6. 验证二叉搜索树

private boolean isValidBST(TreeNode node, long lower, long upper) { if (node == null) return true; if (node.val <= lower || node.val >= upper) return false; return isValidBST(node.left, lower, node.val) && isValidBST(node.right, node.val, upper);}

四、排序与搜索

7. 快速排序

public void quickSort(int[] arr, int low, int high) { if (low < high) { int pi = partition(arr, low, high); quickSort(arr, low, pi - 1); quickSort(arr, pi + 1, high); }}private int partition(int[] arr, int low, int high) { int pivot = arr[high]; int i = low - 1; for (int j = low; j < high; j++) { if (arr[j] < pivot) { i++; swap(arr, i, j); } } swap(arr, i + 1, high); return i + 1;}private void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;}

8. 二分查找

public int binarySearch(int[] nums, int target) { int left = 0, right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; if (nums[mid] == target) return mid; if (nums[mid] < target) left = mid + 1; else right = mid - 1; } return -1;}

五、动态规划

9. 爬楼梯

public int climbStairs(int n) { if (n == 1) return 1; int[] dp = new int[n + 1]; dp[1] = 1; dp[2] = 2; for (int i = 3; i <= n; i++) { dp[i] = dp[i - 1] + dp[i - 2]; } return dp[n];}

10. 最长递增子序列

public int lengthOfLIS(int[] nums) { int[] dp = new int[nums.length]; Arrays.fill(dp, 1); int max = 1; for (int i = 1; i < nums.length; i++) { for (int j = 0; j < i; j++) { if (nums[i] > nums[j]) { dp[i] = Math.max(dp[i], dp[j] + 1); } } max = Math.max(max, dp[i]); } return max;}

六、回溯算法

11. 全排列

public List<List<Integer>> permute(int[] nums) { List<List<Integer>> res = new ArrayList<>(); backtrack(res, new ArrayList<>(), nums); return res;}private void backtrack(List<List<Integer>> res, List<Integer> temp, int[] nums) { if (temp.size() == nums.length) { res.add(new ArrayList<>(temp)); } else { for (int i = 0; i < nums.length; i++) { if (temp.contains(nums[i])) continue; temp.add(nums[i]); backtrack(res, temp, nums); temp.remove(temp.size() - 1); } }}

12. 组合总和

public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> res = new ArrayList<>(); Arrays.sort(candidates); backtrack(res, new ArrayList<>(), candidates, target, 0); return res;}private void backtrack(List<List<Integer>> res, List<Integer> temp,int[] candidates, int remain, int start) { if (remain < 0) return; if (remain == 0) { res.add(new ArrayList<>(temp)); return; } for (int i = start; i < candidates.length; i++) { temp.add(candidates[i]); backtrack(res, temp, candidates, remain - candidates[i], i); temp.remove(temp.size() - 1); }}

七、其他重要算法

13. LRU缓存机制

class LRUCache { class DLinkedNode { int key; int value; DLinkedNode prev; DLinkedNode next; } private Map<Integer, DLinkedNode> cache = new HashMap<>(); private int size; private int capacity; private DLinkedNode head, tail; public LRUCache(int capacity) { this.size = 0; this.capacity = capacity; head = new DLinkedNode(); tail = new DLinkedNode(); head.next = tail; tail.prev = head; } public int get(int key) { DLinkedNode node = cache.get(key); if (node == null) return -1; moveToHead(node); return node.value; } public void put(int key, int value) { DLinkedNode node = cache.get(key); if (node == null) { DLinkedNode newNode = new DLinkedNode(); newNode.key = key; newNode.value = value; cache.put(key, newNode); addNode(newNode); size++; if (size > capacity) { DLinkedNode tail = popTail(); cache.remove(tail.key); size--; } } else { node.value = value; moveToHead(node); } } private void addNode(DLinkedNode node) { node.prev = head; node.next = head.next; head.next.prev = node; head.next = node; } private void removeNode(DLinkedNode node) { DLinkedNode prev = node.prev; DLinkedNode next = node.next; prev.next = next; next.prev = prev; } private void moveToHead(DLinkedNode node) { removeNode(node); addNode(node); } private DLinkedNode popTail() { DLinkedNode res = tail.prev; removeNode(res); return res; }}

14. 实现Trie(前缀树)

class Trie { class TrieNode { TrieNode[] children = new TrieNode[26]; boolean isEnd; } private TrieNode root; public Trie() { root = new TrieNode(); } public void insert(String word) { TrieNode node = root; for (char c : word.toCharArray()) { if (node.children[c - \'a\'] == null) { node.children[c - \'a\'] = new TrieNode(); } node = node.children[c - \'a\']; } node.isEnd = true; } public boolean search(String word) { TrieNode node = searchPrefix(word); return node != null && node.isEnd; } public boolean startsWith(String prefix) { return searchPrefix(prefix) != null; } private TrieNode searchPrefix(String prefix) { TrieNode node = root; for (char c : prefix.toCharArray()) { if (node.children[c - \'a\'] == null) return null; node = node.children[c - \'a\']; } return node; }}

这些算法题目覆盖了Java面试中最常见的数据结构和算法问题。建议不仅要理解这些解决方案,还要能够分析它们的时间复杂度和空间复杂度,并思考可能的优化方法。