LeetCode Hot 100 (5) 普通数组
# 53. 最大子数组和 (opens new window)
题目:
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
2
3
示例 2:
输入:nums = [1]
输出:1
2
示例 3:
输入:nums = [5,4,-1,7,8]
输出:23
2
提示:
- 1 <= nums.length <= 105
- -10^4 <= nums[i] <= 10^4
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
思路:
dp类型问题 dp[i]表示以nums[i]结尾的连续数组的最大和 dp[i] = max(dp[i-1]+nums[i], nums[i])
代码:
C++代码
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n);
dp[0] = nums[0];
int res = dp[0];
for(int i=1;i<n;i++) {
dp[i] = max(dp[i-1]+nums[i],nums[i]);
res = max(res, dp[i]);
}
return res;
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
Go代码
func maxSubArray(nums []int) int {
n := len(nums)
dp := make([]int,n)
dp[0] = nums[0]
res := dp[0]
for i:=1;i<n;i++ {
dp[i] = max(dp[i-1]+nums[i],nums[i])
res = max(res,dp[i])
}
return res
}
2
3
4
5
6
7
8
9
10
11
# 56. 合并区间 (opens new window)
题目:
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
2
3
示例 2:
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
2
3
提示:
- 1 <= intervals.length <= 10^4
- intervals[i].length == 2
- 0 <= starti <= endi <= 10^4
思路:
现根据起始位置对数组排序然后分三种情况讨论
代码:
C++代码
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(),intervals.end());
vector<vector<int>> res;
int st = -1, ed = -1;
for(int i=0;i<intervals.size();i++) {
if(intervals[i][0]>ed) {
if(ed!=-1) {
res.push_back({st,ed});
}
st = intervals[i][0];
ed = intervals[i][1];
} else {
ed = max(ed,intervals[i][1]);
}
}
res.push_back({st,ed});
return res;
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Go代码
func merge(intervals [][]int) [][]int {
n := len(intervals)
res := make([][]int,0);
st, ed := -1, -1
sort.Slice(intervals,func(i int, j int) bool {
return intervals[i][0]<intervals[j][0]
})
for i:=0;i<n;i++ {
if intervals[i][0]>ed {
if ed!=-1 {
res = append(res,[]int{st,ed})
}
st = intervals[i][0]
ed = intervals[i][1]
} else {
ed = max(ed,intervals[i][1])
}
}
if ed!=-1 {
res = append(res,[]int{st,ed})
}
return res
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 189. 轮转数组 (opens new window)
题目:
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
2
3
4
5
6
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
2
3
4
5
提示:
- 1 <= nums.length <= 105
- -2^31 <= nums[i] <= 2^31 - 1
- 0 <= k <= 10^5
进阶:
- 尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
- 你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?
思路:
先反转整个数组,再反转前半部分,再反转后半部分
代码:
C++代码
class Solution {
public:
void rotate(vector<int>& nums, int k) {
int n = nums.size();
int t = k % n;
reverse(nums.begin(),nums.end());
reverse(nums.begin(),nums.begin()+t);
reverse(nums.begin()+t,nums.end());
}
};
2
3
4
5
6
7
8
9
10
Go代码
func rotate(nums []int, k int) {
n := len(nums)
t := k % n
reverse(nums)
reverse(nums[:t])
reverse(nums[t:])
}
func reverse(nums []int) {
l, r := 0, len(nums)-1
for l<r {
nums[l], nums[r] = nums[r], nums[l]
l++
r--
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 238. 除自身以外数组的乘积 (opens new window)
题目:
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。
题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请 不要使用除法,且在 O(n) 时间复杂度内完成此题。
示例 1:
输入: nums = [1,2,3,4]
输出: [24,12,8,6]
2
示例 2:
输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]
2
提示:
- 2 <= nums.length <= 10^5
- -30 <= nums[i] <= 30
- 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内
进阶:你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)
思路:
前后缀积 先预处理出res[i]表示索引i左侧的数的乘积,然后从后往前遍历的过程中求出来最终结果。
代码:
C++代码
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> res(n);
//res[i]表示索引为i左侧的所有数的乘积
res[0] = 1;
for(int i=1;i<n;i++) {
res[i] = nums[i-1]*res[i-1];
}
int t = 1;
for(int i=n-1;i>=0;i--) {
res[i] = res[i]*t;
t *= nums[i];
}
return res;
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Go代码
func productExceptSelf(nums []int) []int {
n := len(nums)
res := make([]int,n)
res[0] = 1
for i:=1;i<n;i++ {
res[i] = res[i-1]*nums[i-1]
}
t := 1
for i:=n-1;i>=0;i-- {
res[i] = res[i] * t
t *= nums[i]
}
return res
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 41. 缺失的第一个正数 (opens new window)
题目:
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0]
输出:3
2
示例 2:
输入:nums = [3,4,-1,1]
输出:2
2
示例 3:
输入:nums = [7,8,9,11,12]
输出:1
2
提示:
- 1 <= nums.length <= 5 * 10^5
- -2^31 <= nums[i] <= 2^31 - 1
思路:
第0个位置应该放1,第1个位置应该放2..... 所以当nums[i]>=1并且小于等于n时,它的位置应该是nums[i]-1
代码:
C++代码
class Solution {
public:
int firstMissingPositive(vector<int>& nums) {
int n = nums.size();
for(int i=0;i<n;i++) {
while(nums[i]>=1&&nums[i]<=n&&nums[i]!=nums[nums[i]-1]) {
swap(nums[i],nums[nums[i]-1]);
}
}
for(int i=0;i<n;i++) {
if(nums[i]!=i+1) {
return i+1;
}
}
return n+1;
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Go代码
func firstMissingPositive(nums []int) int {
n := len(nums)
for i:=0;i<n;i++ {
for nums[i]>=1&&nums[i]<=n&&nums[i]!=nums[nums[i]-1] {
nums[i],nums[nums[i]-1] = nums[nums[i]-1], nums[i]
}
}
for i:=0;i<n;i++ {
if nums[i]!=i+1 {
return i+1
}
}
return n+1
}
2
3
4
5
6
7
8
9
10
11
12
13
14