剑指 Offer II 007. 数组中和为 0 的三个数
思路:由于需要找到和为0的三个数,且要求不重复,所以如果仅仅只使用哈希表是无法解决去重的问题的。(也不能在定义一个哈希表来保存所以的数组去重)
所以本题使用的办法是先将整个数组排序,接下来问题就转化为有序数组中查找。(双指针)
通过判断一指针和二指针是否与上一次遍历的数相同来去重(在注释去重的地方具体实现)注意溢出的问题
代码如下:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if(nums.size() < 3)
return res;
sort(nums.begin(),nums.end());
for(int i = 0;i < nums.size() - 2;i++)
{
//去重
if(i > 0 && nums[i] == nums[i - 1])
continue;
int j = i + 1,x = nums.size() - 1;
int t = -nums[i];
for(;j < nums.size();j++)
{
if(j > i + 1 && nums[j - 1] == nums[j])
continue;
/*为了去重,不使用while循环,转为使用for循环,因此写法是在每一次循环中,判断如果和大于目标,三指针减一,否则判断后,循环。
while(j < x && nums[j] + nums[x] > t)
x--;
if(j == x)
break;
if(nums[x] + nums[j] == t)
res.push_back({nums[i],nums[j],nums[x]});
}
}
return res;
}
};
剑指 Offer II 009. 乘积小于 K 的子数组
此题解法类似,重点在于想到使用滑动窗口。
一段子数组,先确定其右端点,此时左端点越靠右,子数组总乘积就越小,不断逼近找到第一个小于k的左端点。(数组每个成员都大于0)
class Solution {
public:
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
int i = 0,j = 0,n = nums.size(),t = 1,res = 0;
while(j < n)
{
t *= nums[j];
while(i <= j && t >= k)
{
t /= nums[i];
i++;
}
res += j - i + 1;
j++;
}
return res;
}
};