LC605 这道题是分类讨论,果然还是用到了离散数学里面的思想,你要覆盖所有情况, 我当时自己想就没有想全面,这实际上就是自己思维的漏洞,平时生活中这种事情也应该想到,就是考虑全面。比如昨天开车就没有考虑堵车的情况
思维不够缜密,但可以通过这种练习来不断提高。
说回这道题,这道题一共有3种情况,第一种是有一个1为边界的时候,比如左边全是0或者右边都是0,这时候总共能放入的1 有k/2下取整这么多。(这个k是当前线段的长度)当然这个k/2是找规律找出来的。
第二种情况就是在两个1之间,这时候代码里其实不需要特判,因为你遇到1直接跳过就可以了,然后用双指针(就是第二个指针代表遇到的第二个1) 来求这段区间的长度。这时候不用特判就可直接求里面能放多少个1,因为天然符合两个1之间(双指针的做用) 而这里面能放 (k-1)/2 下取整这么多个数(也是通过找规律来得到这个公式)。
我原本以为第三种情况就是右边界的情况,但实际上这种情况在代码里可以直接用没有1(整个数组没有1) 来覆盖掉
第三种情况就是没有1
也就是说如果j(第二个指针) == arr.length 的时候, 那么右边就没有1, 这时候无论是整个数组没有1,还是左边有个1,这段区间的长度里面能够放的1**都为 (k+1)/2 下取整
代码太强了,我看了好几遍才发现这两个if判断直接能够排除第三种(没有1),因为双指针是直接贪心地走右边,那么如果第二个指针能够到最后一位,那直接让k++就可以了(前面判断过i是否为0) 如果i不是0,那么k就不用+1,而他原本就是直接求出k-1的长度(k本身是真正的长度,但他直接把k存成了k-1,这样之后就不用考虑第二种情况了(两个1之间)。
代码
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
if (n == 0) return true;
boolean leftBound = true, inBetween = false;
int count = 0, m = flowerbed.length;
for (int i = 0; i < m; i++) {
if (flowerbed[i] == 1) continue;
int j = i;
while (j < m && flowerbed[j] == 0) {
j++;
}
int k = j - i - 1; // 直接存k-1,这样不用再算(k-1)之后 再(k-1)/2下取整了
if (i == 0) k++; //特判左边界,如果为0,那就是第一种情况,这时候能够放下的1就是k/2个了,所以k++;
if (j == flowerbed.length) k++; // 如果第二个指针是最后一位了,那么无论之前是啥情况,我们都要k+1,(如果左指针是0,那么我们之前if已经判断过了,如果不是0,我们也要k++,因为第一种情况,也就是只有一个1的边界的时候,我们能够放k/2个1
count += k / 2;
i = j;
}
return count >= n;
}
}
网友评论