在这篇文章中,我将带你一起深入分析5道Java岗高频的LeetCode算法题,通过场景化拆解,结合,从浅入深进行讲解。我会在每道题目后附上详细的代码实现,并探究一些优化本领和背后的算法理论,希望能资助你在面试中脱颖而出。
1. 题目一:两数之和(Two Sum)
场景化配景
假设你正在开发一个电商平台,用户在结算时输入一个目的金额,你需要帮用户找出购物车中两个商品的总价是否即是这个金额。假如找到了,就返回这两个商品的索引。这个题目看似简朴,但如何设计高效的算法却磨练着我们对数据结构的理解。
题目形貌
给定一个整数数组 nums 和一个目的值 target,请你在该数组中找出和为目的值 target 的两个数,并返回它们的数组下标。
解法一:暴力解法
暴力解法最直接,遍历数组中的每一对数,查抄它们的和是否即是目的值。
- public class TwoSum {
- public int[] twoSum(int[] nums, int target) {
- for (int i = 0; i < nums.length; i++) {
- for (int j = i + 1; j < nums.length; j++) {
- if (nums[i] + nums[j] == target) {
- return new int[] {i, j};
- }
- }
- }
- throw new IllegalArgumentException("No two sum solution");
- }
- }
复制代码 代码分析
- 时间复杂度:O(n^2),由于我们需要遍历所有的元素组合。
- 空间复杂度:O(1),没有利用额外的空间。
解法二:哈希表解法
哈希表是一种非常得当查找题目的数据结构,通过哈希表,我们可以在遍历数组的同时查找目的元素,克制了暴力解法的双重循环。
- import java.util.HashMap;
- public class TwoSum {
- public int[] twoSum(int[] nums, int target) {
- HashMap<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");
- }
- }
复制代码 代码分析
- 时间复杂度:O(n),每个元素最多被访问两次:一次用于查找,另一次用于插入哈希表。
- 空间复杂度:O(n),需要额外的哈希表来存储元素。
在面试中,虽然暴力解法是最直观的,但是面试官更看重的是你的思维广度和深度。哈希表的解法不但减少了时间复杂度,而且充分展示了你对数据结构的理解和运用。在实际项目中,我们也常常利用哈希表来做快速查找,效率上能够得到明显提升。
2. 题目二:无重复字符的最宗子串(Longest Substring Without Repeating Characters)
场景化配景
假设你正在开发一个文本编辑器功能,需要处置惩罚一个输入字符串,找出其中最长的不包罗重复字符的子串。这类题目在字符串处置惩罚、数据流分析等场景中非常常见。
题目形貌
给定一个字符串,找出其中不含有重复字符的最宗子串的长度。
解法:滑动窗口法
滑动窗口是一种优化的技能,通常用于查找满意某些条件的子数组或子串。通过利用两个指针来维护一个滑动窗口,在窗口内查找最优解。
- import java.util.HashSet;
- public class LongestSubstring {
- public int lengthOfLongestSubstring(String s) {
- HashSet<Character> set = new HashSet<>();
- int left = 0, right = 0;
- int maxLength = 0;
-
- while (right < s.length()) {
- if (!set.contains(s.charAt(right))) {
- set.add(s.charAt(right));
- right++;
- maxLength = Math.max(maxLength, right - left);
- } else {
- set.remove(s.charAt(left));
- left++;
- }
- }
-
- return maxLength;
- }
- }
复制代码 代码分析
- 时间复杂度:O(n),每个字符最多访问两次,分别是左指针和右指针。
- 空间复杂度:O(min(n, m)),其中n是字符串的长度,m是字符集的巨细(通常是256)。
滑动窗口技能在处置惩罚这类动态窗口题目时非常高效。它不但仅是一个算法本领,还能资助我们在实际开发中提高处置惩罚复杂字符串或数组题目的本事。面试中,这种方法能够展示你对窗口技能的掌握,给面试官留下深刻印象。
3. 题目三:归并区间(Merge Intervals)
场景化配景
假设你正在为一个集会室管理系统开发功能,多个用户大概会预定同一时间段的集会室。你需要归并重叠的时间段,克制重复预定。
题目形貌
给定一组区间,归并所有重叠的区间。
解法:排序法
首先对区间按开始时间进行排序,然后遍历区间,归并重叠区间。
- import java.util.Arrays;
- import java.util.ArrayList;
- public class MergeIntervals {
- public int[][] merge(int[][] intervals) {
- if (intervals.length == 0) return new int[0][0];
-
- Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
- ArrayList<int[]> merged = new ArrayList<>();
-
- for (int[] interval : intervals) {
- if (merged.isEmpty() || merged.get(merged.size() - 1)[1] < interval[0]) {
- merged.add(interval);
- } else {
- merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], interval[1]);
- }
- }
-
- return merged.toArray(new int[merged.size()][]);
- }
- }
复制代码 代码分析
- 时间复杂度:O(n log n),排序的时间复杂度。
- 空间复杂度:O(n),存储归并后的区间。
这个题目考察了你如何通过排序和线性遍向来解决题目。这种思路对于处置惩罚区间类题目非常有用,而且在实际开发中有广泛应用,好比任务调度、资源管理等。
4. 题目四:有用的括号(Valid Parentheses)
场景化配景
假设你正在开发一个编译器或表明器,编译时需要查抄步伐代码中的括号是否匹配。这是一个经典的栈应用题目。
题目形貌
给定一个字符串,包罗只由 ()、[]、{} 三种括号组成的字符串,判定字符串是否有用。
解法:栈解法
栈是一种非常得当括号匹配的工具。遇到左括号时入栈,遇到右括号时与栈顶元素匹配。
- import java.util.Stack;
- public class ValidParentheses {
- public boolean isValid(String s) {
- 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();
- }
- }
复制代码 代码分析
- 时间复杂度:O(n),每个字符最多入栈和出栈一次。
- 空间复杂度:O(n),栈最多存储n个字符。
栈是一种非常经典的数据结构,尤其得当处置惩罚括号匹配题目。在面试中,假如你能熟练运用栈来解决括号匹配等题目,面试官会以为你对数据结构有较深的理解。
5. 题目五:反转链表(Reverse Linked List)
场景化配景
假设你正在开发一个链表处置惩罚库,需要实现链表反转功能。这是链表类题目中非常经典的题目,适用于许多实际应用。
题目形貌
反转一个单链表。
解法:迭代法
通过迭代渐渐反转链表中的每个节点。
- public class ReverseLinkedList {
- 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;
- }
- }
复制代码 代码分析
- 时间复杂度:O(n),需要遍历整个链表一次。
- 空间复杂度:O(1),不需要额外的空间。
链表反转是一个非常常见且实用的题目,它考察了你对链表操作的熟悉程度。在实际开发中,链表反转常用于缓存系统、队列实现等场景,掌握链表操作对Java开发者非常重要。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |