根据vivo提前批笔试题目顺序,依次带来这三道LeetCode题目。
以上图片就是vivo第一题,来自LeetCode 605. Can Place Flowers,一道easy题,比较简单。
Problem Description:
Suppose you have a long flowerbed in which some of the plots are planted and some are not. However, flowers cannot be planted in adjacent plots - they would compete for water and both would die.
Given a flowerbed (represented as an array containing 0 and 1, where 0 means empty and 1 means not empty), and a number n, return if n new flowers can be planted in it without violating the no-adjacent-flowers rule.
Example 1:
Input: flowerbed = [1,0,0,0,1], n = 1
Output: True
Example 2:
Input: flowerbed = [1,0,0,0,1], n = 2
Output: False
Note:
1.The input array won’t violate no-adjacent-flowers rule.
2.The input array size is in the range of [1, 20000].
3.n is a non-negative integer which won’t exceed the input array size.
直接求解的思路很简单,遍历所有元素,找出值为0的元素(意味着这是一个空位置)。对于元素值为0元素,检查它的两个相邻位置是否也是0。如果满足以上条件这样,我们可以在当前位置种植一朵花flowerbed[index] = 1;
,而不违反禁止相邻种花的规则。对于第一个元素,不需要检查它的前一个元素;对于最后一个元素,不需要检查下一个元素。
((当前元素=0) && (第一个元素||前一个元素=0) && (最后一个元素||后一个元素=0))
((flowerbed[index] == 0) && ((index == 0) || (flowerbed[index-1] == 0)) && ((index == flowerbed.length-1) || (flowerbed[index+1] == 0)))
找到一个位置,计数+1,若大于等于初始给定的n,则返回true。所有元素遍历完成后,仍未大于等于初始给定的n,则返回false。
注意:
一定要注意((index == 0) || (flowerbed[index-1] == 0))
和((index == flowerbed.length-1) || (flowerbed[index+1] == 0))
,要采用 || 的短路操作,使(index == 0)
和(index == flowerbed.length-1)
先进行判断,否则会造成数组下标越界。
对于vivo原题,只需要遍历计数,直接返回计数总数即可。
算法时间复杂度为O(n),空间复杂度为O(1)
//Time complexity : (n).
//Space complexity : O(1).
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int index = 0;
int cnt = 0;
while(index < flowerbed.length){
//((当前元素=0) && (第一个元素||前一个元素=0) && (最后一个元素||后一个元素=0))
if((flowerbed[index] == 0) && ((index == 0) || (flowerbed[index-1] == 0)) && ((index == flowerbed.length-1) || (flowerbed[index+1] == 0))){//关键:||短路操作
flowerbed[index] = 1;//需要这一步
cnt++;
}
if(cnt >= n){
return true;
}
index++;
}
return false;
}
}
优化解法的关键在于:
1.The input array won’t violate no-adjacent-flowers rule.
由于输入的数组也满足禁止相邻种花的规则,所以元素值=1的元素前后位置的值一定=0,即010。
伪代码:
‘0’或‘1’:当前遍历元素
X:下一个遍历元素
if(当前元素值=1)
根据The input array won't violate no-adjacent-flowers rule.条件,其前后元素一定=0,即0‘1’0X,所以索引可以直接+2遍历元素X
else // 当前元素值=0
(隐含条件:如果当前元素的前一个元素值=1,根据上面描述索引直接+2,无法遍历到当前元素,假设不成立,所以当前元素的前一个元素一定=0)
if(下一个元素值=0)
0‘0’0X,可以种植,计数+1,索引直接+2遍历下一个元素X
else // 下一个元素值=1
因为下一个元素值=1,根据The input array won't violate no-adjacent-flowers rule.条件,则下下一个元素值=0,即0‘0’10X,索引直接+3遍历元素X。其实,对于下一个元素1来说,也就是索引+2。
根据分析伪代码的所有情况,当前遍历元素和下一个遍历元素X的前一个元素值一定=0(这点是非常重要的!),所以根据以上优化算法的思想,我们不再需要判断当前遍历元素的上一个元素值。(如果这里不明白的,可以停下来多思考一下,或者在纸上画一下就比较清楚了)
边界条件:防止数组下标越界
①由于不需要考虑当前遍历元素的前一个元素,所以自然不用考虑第一个元素。
②考虑最后一个元素,要先进行索引值判断(index == flowerbed.length-1)
,也是采用 || 短路操作来实现 ((index == flowerbed.length-1) || (flowerbed[index+1] == 0))
算法时间复杂度为O(n),空间复杂度为O(1)
此优化方法不需要判断当前遍历元素的前一个元素值,且每次遍历索引+2或+3,加速了数组的遍历。
//关键:The input array won't violate no-adjacent-flowers rule.
//Time complexity : 少于O(n/2).
//Space complexity : O(1).
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int index = 0;
int cnt = 0;
while(index < flowerbed.length){
if(flowerbed[index] == 1){
index += 2;
}else{//flowerbed[index] == 0,
if((index == flowerbed.length-1) || (flowerbed[index+1] == 0)){//关键:||短路操作
//flowerbed[index] = 1;//不需要这一步
cnt++;
index += 2;
}else if(flowerbed[index+1] == 1){
index += 3;
}
}
if(cnt >= n){
return true;
}
}
return false;
}
}