1034-乘积小于 K 的子数组

题目如下

给定一个正整数数组 nums和整数 k ,请找出该数组内乘积小于 k 的连续的子数组的个数。

示例 1:
输入: nums = [10,5,2,6], k = 100
输出: 8
解释: 8 个乘积小于 100 的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。
需要注意的是 [10,5,2] 并不是乘积小于100的子数组。

示例 2:
输入: nums = [1,2,3], k = 0
输出: 0

解题思路

1.要用滑窗这个思路来解题的方向比较好确定,这一步比较简单
2.滑窗内求乘积也好求,那么判断比较k和乘积的大小也好说
3.下一步滑窗内的子数组个数这个不难,但是问题在于滑动窗口移动后可能和之前的滑窗有重叠,这样我们需要解决怎么去除掉重复统计到的子数组数量的问题了,好像比较麻烦,其实也不是不行,还是有方法的(子数组左右边界求哈希,再用哈希表判断重复,不过此处不是重点,我们继续后面的思考)
4.这样我们需要知道不同子数组区间,他们的子数组有重叠的情况是因为滑窗左边或者右边移动引起的,而我们这一题中的滑窗左右边界是永远都往右移动的
5.那么,当左边界往右移动的时候产生的都是重复的连续子数组,只有右边界往右移动的时候才会产生新的连续子数组
6.所以
只有在右边界往右移动的时候才去统计以右边界为结束的子数组的数量
以右边界为结束的子数组的数量即为这个子数组的长度 right - left + 1

解题代码

class Solution
{
public:
	int numSubarrayProductLessThanK(vector<int>nums, int k)
	{
		int ans = 0;
		int left = 0;
		int right = 0;
		int n = nums[0];
		if (n < k)
		{
			//初始一个是否需要的判断
			ans = 1;
		}
		while (true)
		{
			if (n >= k)
			{
				//如果当前乘积大于等于,则需要右移左边界,并除去相应的值
				n /= nums[left];
				left++;
				if (left > right)
				{
					//如果左边界在右边界右边了,需要同时移动右边界
					right++;
					if (right == nums.size())
					{
						//如果右边界越界了,则终止
						break;
					}
					n *= nums[right];
				}
			}
			else
			{
				//如果当前乘积小于,则需要右移右边界,并乘上相应的值
				right++;
				if (right == nums.size())
				{
					//如果右边界越界了,则终止
					break;
				}
				n *= nums[right];
			}
			if (n < k)
			{
				//经过本轮移动之后的乘积值判断,并统计数量
				ans += right - left + 1;
			}
		}
		return ans;
	}
};
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值