剑指offer 专项突破版 9、乘积小于 K 的子数组

本文讲解了如何利用双指针法解决题目,涉及判断数组中乘积小于k的子数组数量,重点在于移动right指针后的子数组计数逻辑。通过实例和代码演示,阐述了空间复杂度和时间复杂度,并强调了在product大于目标值时调整left指针的方法。
摘要由CSDN通过智能技术生成

题目链接

首先需要明确何时可以使用双指针法,一定是right向前移动时和或者时积要增大

思路:双指针

最主要的一点在于,当right移动后product仍然小于k时,此时的子数组的数目为right + left - 1
ex:nums = [10,5,1,6], k = 100

  • 最初left = right = 0,此时有1个子数组[10];然后right=1,此时product<100,新增两个子数组[5],[10,5];然后right=2,此时仍有procudt<100,新增三个子数组[1],[5,1],[10,5,1]。也就是说如果最后product < 100,那么肯定会新增right-left+1个子数组
  • 但是当product > 100时,我们需要用product/nums[left],然后left右移,直到product<100或者是left>right,那么如何判断最后是否会新增子数组呢?答案就是判断是否有right>=left
时空复杂度
  • 时间复杂度:遍历一遍O(n)
  • 空间复杂度:额外空间恒定O(1)
public int numSubarrayProductLessThanK(int[] nums, int k) {
        int count = 0, left = 0, product = 1;

        for (int right = 0; right < nums.length; right++) {
            product *= nums[right];

            while (product >= k && left <= right) {
                product /= nums[left++];
            }
            count += right >= left ? right - left + 1 : 0;
        }
        return count;
    }

Go代码

func numSubarrayProductLessThanK(nums []int, k int) int {

	left, right, mul, result := 0, 0, 1, 0

	for right < len(nums) {
		mul *= nums[right]
        for mul >= k && left <= right{
			mul /= nums[left]
			left++
		}
		
		result += right - left + 1
        right++
	}
	
	return result
}

这道题的关键在于 right++ 后,新增的子数组个数为right-left+1,那么有几个子数组符合要求呢?答案是需要找到最小的left使得nums[left] * nums[left+1] … * nums[right] < target,这样符合条件的子数组的个数为right-left+1
还有一点需要注意的是,在找left的时候有可能不存在这样的子数组,所以内部循环需要增加一个条件就是left<=right(这是和前一道题不一样的地方)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值