LeetCode Hot 100
53. 最大子数组和
难度:中等 | LeetCode 链接
给定一个整数数组 nums,找到一个具有最大和的连续子数组,返回其最大和。
1 2 3
| 输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:子数组 [4,-1,2,1] 的和最大,为 6
|
思路
贪心/动态规划:当前位置的最大子数组和只与前一位置的结果相关。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Solution { public int maxSubArray(int[] nums) { int pre = 0; int ans = nums[0]; for(int i=0;i<nums.length;i++){ pre = Math.max(pre+nums[i],nums[i]); ans = Math.max(ans,pre); } return ans; } }
|
复杂度:时间 O(n),空间 O(1)
56. 合并区间
难度:中等 | LeetCode 链接
以数组 intervals 表示若干个区间,合并所有重叠的区间。
1 2
| 输入:intervals = [[1,3],[2,6],[8,10],[15,18]] 输出:[[1,6],[8,10],[15,18]]
|
思路
按起点排序后线性合并。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Solution { public int[][] merge(int[][] intervals) { Arrays.sort(intervals,(a,b) -> (a[0]-b[0])); List<int[]> ans = new ArrayList<>(); for(int i =0;i<intervals.length;i++){ int size = ans.size(); if(size>0&&ans.get(size-1)[1]>=intervals[i][0]){ ans.get(size-1)[1] = Math.max(ans.get(size-1)[1],intervals[i][1]); }else{ ans.add(intervals[i]); } } return ans.toArray(new int[0][]); } }
|
复杂度:时间 O(n log n),空间 O(n)
189. 轮转数组
难度:中等 | LeetCode 链接
给你一个数组,将数组中的元素向右轮转 k 个位置。
1 2
| 输入:nums = [1,2,3,4,5,6,7], k = 3 输出:[5,6,7,1,2,3,4]
|
思路
通过取模计算新索引位置,使用额外数组存储结果后覆盖原数组。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class Solution { public void rotate(int[] nums, int k) { int len = nums.length; int[] ans = new int[len]; for(int i=0;i<len;i++){ ans[(i+k)%len] = nums[i]; } System.arraycopy(ans,0,nums,0,len); } }
|
复杂度:时间 O(n),空间 O(n)
238. 除自身以外数组的乘积
难度:中等 | LeetCode 链接
给你一个数组 nums,返回数组 answer,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
1 2
| 输入:nums = [1,2,3,4] 输出:[24,12,8,6]
|
思路
先算左侧前缀乘积,再从右往左乘上右侧前缀乘积。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public int[] productExceptSelf(int[] nums) { int n = nums.length; int[] res = new int[n]; res[0] = 1; for (int i = 1; i < n; i++) { res[i] = res[i - 1] * nums[i - 1]; } int right = 1; for (int i = n - 1; i >= 0; i--) { res[i] = res[i] * right; right *= nums[i]; } return res; } }
|
复杂度:时间 O(n),空间 O(1)(不计输出)
41. 缺失的第一个正数
难度:困难 | LeetCode 链接
给你一个未排序的整数数组 nums,请你找出其中没有出现的最小的正整数。
1 2
| 输入:nums = [3,4,-1,1] 输出:2
|
思路
原地哈希:把 1..n 放到对应下标位置 x -> x-1,再扫一遍找第一个不匹配的位置。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Solution { public int firstMissingPositive(int[] nums) { int n = nums.length; for (int i = 0; i < n; i++) { while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) { int tmp = nums[i]; nums[i] = nums[tmp - 1]; nums[tmp - 1] = tmp; } } for (int i = 0; i < n; i++) { if (nums[i] != i + 1) { return i + 1; } } return n + 1; } }
|
复杂度:时间 O(n),空间 O(1)
总结
| 题目 |
核心技巧 |
时间 |
空间 |
| 最大子数组和 |
贪心/DP |
O(n) |
O(1) |
| 合并区间 |
排序 + 扫描 |
O(n log n) |
O(n) |
| 轮转数组 |
三次翻转 |
O(n) |
O(1) |
| 除自身以外数组的乘积 |
前缀积 |
O(n) |
O(1) |
| 缺失的第一个正数 |
原地哈希 |
O(n) |
O(1) |