334.递增的三元子序列
给你一个整数数组nums
,判断这个数组中是否存在长度为3
的递增子序列。
如果存在这样的三元组下标(i, j, k)
且满足i < j < k
,使得nums[i] < nums[j] < nums[k]
,返回true
;否则,返回false
。
示例1
输入:nums = [1,2,3,4,5]
输出:true
解释:任何 i < j < k 的三元组都满足题意
示例2
输入:nums = [5,4,3,2,1]
输出:false
解释:不存在满足题意的三元组
示例3
输入:nums = [2,1,5,0,4,6]
输出:true
解释:三元组 (3, 4, 5) 满足题意,因为 nums[3] == 0 < nums[4] == 4 < nums[5] == 6
提示:
1 <= nums.length <= 5 * 10^5
-2^31 <= nums[i] <= 2^31 - 1
进阶:你能实现时间复杂度为O(n)
,空间复杂度为O(1)
的解决方案吗?
思路
这道题关键就是要贪!题目说要下标和数值都递增对吧,那我之间要求数组中的第一个元素不但是数组中最小的,也要是所有遍历过的最小值,第二个元素也要尽可能地小,只要大于第一个就好了。然后动态维护这两个值,如果nums[i]
小于等于第一个元素,那么就更新第一个元素;如果介于第一个和第二个元素之间,就更新第二个元素;如果大于第二个元素,那好事就来了,就可以返回true
了。
代码
bool increasingTriplet(vector<int>& nums) {
int minVal = INT_MAX, maxVal = INT_MAX;
for (auto num : nums){
if (num <= minVal){
minVal = num;
}
else if (num <= maxVal){
maxVal = num;
}
else{
return true;
}
}
return false;
}
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]
提示
2 <= nums.length <= 10^5
-30 <= nums[i] <= 30
- 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在32 位整数范围内
进阶:你可以在O(1)的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)
思路
这道题因为不让用乘法,所以不能先求总乘积再分别除以本身。那么这道题就可以想一下前缀,对于nums[i]
,它除自身以外数组的乘积为nums[0]
逐个乘到nums[i-1]
再乘上nums[i+1]
逐个乘到nums[n-1]
。那么我们可以把左右分开来乘,定义left是nums[i]
左侧所有元素的乘积,right是nums[i]
右侧所有元素的乘积,一个从左往右迭代,一个从右往左迭代,当遍历完成时,每个位置都已满足题目要求。
代码
vector<int> productExceptSelf(vector<int>& nums) {
int n = nums.size();
vector<int> answer(n, 1);
int left = 1, right = 1;
for (int i = 0; i < n; i++){
answer[i] *= left;
left *= nums[i];
int m = n - 1 - i;
answer[m] *= right;
right *= nums[m];
}
return answer;
}
560.和为K的子数组
给你一个整数数组nums
和一个整数k
,请你统计并返回该数组中和为k
的子数组的个数 。
示例1
输入:nums = [1,1,1], k = 2
输出:2
示例2
输入:nums = [1,2,3], k = 3
输出:2
提示
1 <= nums.length <= 2 * 10^4
-1000 <= nums[i] <= 1000
-10^7 <= k <= 10^7
思路
使用前缀和,用一个哈希表
p
r
e
pre
pre记录本元素前所有元素的和,如果
p
r
e
−
k
pre-k
pre−k在这个表中,就说明
p
r
e
[
i
]
=
p
r
e
[
j
]
−
k
pre[i]=pre[j]-k
pre[i]=pre[j]−k,即从
i
i
i到
j
j
j之间所有元素的和等于
k
k
k,计数就+1。
代码
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> mp;
mp[0] = 1;
int count = 0, pre = 0;
for (auto& x:nums) {
pre += x;
if (mp.find(pre - k) != mp.end()) {
count += mp[pre - k];
}
mp[pre]++;
}
return count;
}
本文题目及部分解答来自力扣:334.递增的三元子序列、238.除自身以外数组的乘积和560.和为K的子数组。