前言
滑动窗口可以解决连续子数组问题,以O(n)的时间复杂度为开销。每个节点最多访问两个,所以要思考O(n2)为什么每个节点要被访问N次?
一、乘积小于K的子数组
二、题解
滑动窗口,每改变一次窗口大小,记一部分数,如此反复,每次计自己该计的数,不给下一次带来额外麻烦。各司其职,完成大问题的解决。
package com.xhu.offer.offerII;
public class NumSubarrayProductLessThanK {
public int numSubarrayProductLessThanK(int[] nums, int k) {
if (k == 0) return 0;
int count = 0;
int begin = 0, sum = 1;
for (int i = 0; i < nums.length; i++) {
sum *= nums[i];
if (sum < k) count += i - begin + 1;
if (sum >= k) {
while (begin <= i) if ((sum /= nums[begin++]) < k) break;
count += i - begin + 1;
}
}
return count;
}
}
总结
1)总结:注意审题,都是正整数,这些条件可能是降低时空的因素,甚至可能是解题的关键。 2)总结:代码是给机器看的,是教机器一步一步解决问题的,也就是拆解了问题,不要上来就想if解决所有问题,要拆解成一块一块的循环体。 3)总结:找到规律,即核心迭代块。(所以说循环很关键,循环思维真的很关键。)人要有算法的解决问题,不是暴力解决问题,这样机器才能按照算法走,减少计算量。 4)总结:从小问题到大问题,多个简单问题堆叠成一个复杂问题,复杂性体现在多个简单问题之间碰撞所产生的多现象性。看起来就会很复杂,需挖掘复杂问题中暗含的简单问题。 5)人脑知道该以这样的方式来算,但是没这个时间和超强记忆力,只是借助计算机来算,而思想体现在自己的逻辑,这个逻辑体现在巧妙,而不是时空量去堆积。 6)算法题就是用来训练逻辑的,没有那么多的if,主要是循环的核心体,和相应的数据结构应用。(这是面对算法题的态度和角度去看它,去挖掘,不是无方向无目的的) 7)以整体的方式看数组,比如把数组拆成左中右数组;以局部的方式看内部处理;从局部解决向整体靠近,完成整体的解决。 如,当数组只有一个元素时,该怎么解决?有两个时,该怎么解决?有三个时,可不可以利用2+1解决?n个时,是否可以当作(n - 1) + 1解决。不同情况的相同解决点在那里?
参考文献
[1] LeetCode 原题
|