通过万岁!!!
- 题目:要求在一个数组中,找到所有连续子数组,然后要求子数组的乘积不能超过k,然后问满足条件的子数组的个数。
- 基础思路:双指针,l在左边,每次让乘积*右指针,然后判断是不是满足条件,如果满足,则ans++,如果不满足,则做指针需要右移一位,这时候让右指针回到做指针的位置即可。但是这样的时间复杂度很高。不过也是一种方法。消耗时间为多少千毫秒。
- 莫名其妙的进阶思路:我是想通过每个位置上的最长子数组长度进行求解。这样我们在l位置的长度如果是a,那么r=l+a,则i+1位置只需要从l+a的下一个开始找就行了。但是最后发现,这些长度求和就是最终结果,咱也不知道为啥。我还是说一下我进阶的思路,就是我们知道每个位置的最长子数组之后,从这个位置开始,其实我们能拿到的数组个数是1+…+a,也就是(a+1)*a/2,然后下一个位置如果小于a,则表示我们已经计算过了,然后如果等于a,则个数+=2即可,如果大于a,则减去中间重合的部分,也就是减去。但是这个思路我还没有验证对不对,模模糊糊的写的。
- 技巧:
java代码——基础思路
class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
// 滑动窗口,快慢指针
int n = nums.length;
int l = 0, r = 0;
int product = nums[0];// 当前成绩
int ans = 0;
while (l <= r && r < n) {// 判断product是不是可以
if (product < k) {
if (r < n - 1) {
product *= nums[++r];
} else {// 右指针到头
if (l < n - 1) {// 左指针没有到头
product = nums[++l];
r = l;// r需要回来
} else {// 做指针也到头了
l++;
}
}
ans++;
} else {
if (l < n - 1) {
product = nums[++l];
r = l;// r需要回来
} else {
l++;
}
}
}
return ans;
}
}
java——莫名其妙的进阶思路
class Solution {
public int numSubarrayProductLessThanK(int[] nums, int k) {
// 滑动窗口,快慢指针
if (k == 0) {
return 0;
}
int n = nums.length;
int ans = 0, l = 0, r = 0, product = 1;
int res = 0;
while (l <= r && r < n) {
product *= nums[r];
if (product >= k) {
res += ans;
product /= nums[l++];
if (l - 1 != r)
product /= nums[r];// 取消掉本次的乘,因为下面l++,以后还是需要判断这个r是不是可以
if (l > r) r = l;
if (ans > 0)
ans--;
} else {
r++;
ans++;
}
}
for (int i = n - 1; i >= l; i--) {
res += (n - i);
}
return res;
}
}
- 总结:题目还是比较有意思的,不知道为啥莫名其妙的就对了应该是里面有一些数学推导,我没有进行,时间降到了6ms左右,虽然打败的人数不多,但是比基础思路提升了好多。