53.最大子数组和
题目
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组
是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1] 输出:1
示例 3:
输入:nums = [5,4,-1,7,8] 输出:23
思路
一看就感觉要用动态规划,设dp[i]为前i个字符串中连续子数组的最大和,那么 dp[i] = max(dp[i-1]+nums[i],nums[i])
即在原来的基础上选用这个num[i]或者直接用num[i]
不过最大值不一定是最后的dp[-1],故需要一个res用来保存中间出现过的最大值
代码如下:
class Solution {
public:int maxSubArray(vector<int>& nums) {vector<int> dp(nums.size(),0);dp[0] = nums[0];int ans = nums[0];for(int i = 1;i<nums.size();i++){dp[i] = max(dp[i-1]+nums[i],nums[i]);ans = max(ans,dp[i]);}return ans;}};
不过其实优化一下使用前缀和也可以:
class Solution(object):def maxSubArray(self, nums):""":type nums: List[int]:rtype: int"""sum = 0res = nums[0] for num in nums:sum += numif sum <= num:sum = numres = max(res,sum)return res
56.合并区间
题目
以数组 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:
输入:intervals = [[1,4],[4,5]] 输出:[[1,5]] 解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
思路
第一想法肯定要按照左区间排序,然后不断进行合并merge,第二部没有想的特别清楚导致出错。。。后面看了题解后发现可以用一个下标进行答案数组的遍历来进行更新,代码如下:
class MyCompare{
public:bool operator()(vector<int> T1,vector<int> T2){return T1[0] < T2[0]; }
};
class Solution {
public:vector<vector<int>> merge(vector<vector<int>>& intervals) {sort(intervals.begin(),intervals.end(),MyCompare());vector<vector<int>> ans;int idx = -1;for(auto& nums:intervals){if(idx != -1 && nums[0] <= ans[idx][1]){ans[idx][1] = max(ans[idx][1],nums[1]); //使用答案数组进行遍历更新}else{ans.push_back(nums);idx++;}}return ans;}
};
189.轮转数组
题目
给定一个整数数组 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:
输入:nums = [-1,-100,3,99], k = 2 输出:[3,99,-1,-100] 解释: 向右轮转 1 步: [99,-1,-100,3] 向右轮转 2 步: [3,99,-1,-100]
思路
首先想到k要取个模然后就有点卡壳,后面感觉这种轮转的能够跟旋转搭上关系,如果先旋转一次后再对k取模的前一块和后一块进行旋转便是答案,代码如下:
class Solution {
public:void Reverse(vector<int>& nums,int start,int end){while(start < end){swap(nums[start],nums[end]);start++;end--; }}void rotate(vector<int>& nums, int k) {k = k % nums.size();Reverse(nums,0,nums.size()-1);Reverse(nums,0,k-1);Reverse(nums,k,nums.size()-1);}
};
238.除自身以外数组的乘积
题目
给你一个整数数组 nums
,返回 数组 answer
,其中 answer[i]
等于 nums
中除 nums[i]
之外其余各元素的乘积 。
题目数据 保证 数组 nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。
请 不要使用除法,且在 O(*n*)
时间复杂度内完成此题。
示例 1:
输入: nums = [1,2,3,4] 输出: [24,12,8,6]
示例 2:
输入: nums = [-1,1,0,-3,3] 输出: [0,0,9,0,0]
思路
限制使用除法,那么就只能靠乘积,而乘积的话必须要把自己扔掉,发现可以错位相乘得出答案
例如示例1,2,3,4,第一遍可以将其变成1,1,2,6,然后反向遍历乘法的时候24,12,4,1
再比如2,3,4,5,第一遍可以变成1,2,6,24,然后反向的时候变成60,20,5,1
同样得到答案,即两遍遍历即可,代码如下:
class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {vector<int> result(nums.size(),1);int k = 1;for(int i = 0;i < nums.size();i++){result[i] = k;k *= nums[i];}k = 1;for(int i = nums.size()-1;i >= 0;i--){result[i] *= k;k *= nums[i];}return result;}
};
41.缺失的第一个正数
题目
给你一个未排序的整数数组 nums
,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n)
并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0] 输出:3 解释:范围 [1,2] 中的数字都在数组中。
示例 2:
输入:nums = [3,4,-1,1] 输出:2 解释:1 在数组中,但 2 没有。
示例 3:
输入:nums = [7,8,9,11,12] 输出:1 解释:最小的正数 1 没有出现。
思路
感觉要用哈希,,,并且也实现了一下,不过空间复杂度不符合要求,后面感觉只能对原数组进行修改,
由鸽巢原理数组长度为len,除非数组中正好有1-len的时候答案为len+1,否则答案一定在1-len中可以找到
1.首先先把负数和0剔除掉,将其改为len+1
2.然后原地哈希,对于在1-len之间的数字k,其对应下标k-1的数字num[k-1]变为-abs(num[k-1]),利用负号将这个数出现过的信息存下
3.第三遍便利的时候只需要找到正数然后返回下标+1即可,如果遍历也找不到正数,那么就返回len+1
代码如下:
class Solution(object):def firstMissingPositive(self, nums):l = len(nums)for i in range(l):if nums[i] <= 0:nums[i] = l+1for i in range(l):num = abs(nums[i])if num <= l:nums[num-1] = -abs(nums[num-1])for i in range(l):if nums[i] > 0:return i+1return l+1