使用最少数量的开关打开所有灯泡

时间:2016-03-08 05:16:06

标签: java algorithm bit-manipulation

我正在尝试理解here给出的问题及其解决方案:

问题是:

N个灯泡通过电线连接。每个灯泡都有一个与之相关的开关,但由于接线错误,开关也会将所有灯泡的状态改变为电流灯泡的右侧。给定所有灯泡的初始状态,找到您必须按下以打开所有灯泡的最小开关数。您可以多次按下同一个开关。

注意:0代表灯泡关闭,1代表灯泡开启。

Example:

Input : [0 1 0 1]
Return : 4

Explanation :

press switch 0 : [1 0 1 0]
press switch 1 : [1 1 0 1]
press switch 2 : [1 1 1 0]
press switch 3 : [1 1 1 1]

给出的答案之一是:

int solve(int A[], int N) {

    int state= 0, ans = 0;
    for (int i = 0; i < N;i++) {
        if (A[i] == state) {
            ans++;
            state = 1 - state;
        }
    }

    return ans;
}

我似乎无法理解if语句如何做正确的事情。

4 个答案:

答案 0 :(得分:5)

每当我们翻转一个开关时,我们将所有开关向右翻转,所以如果我们现在搜索0(关闭开关),我们需要搜索1(在开关上),因为我们已经将所有开关向右翻转,让我们看一个例子: 0 1 1 0,现在最初状态= 0,当我们遇到第一个灯泡时,我们翻转所有开关,即1 0 0 1但是在数组中值仍然是0 1 1 0,所以我们需要能够识别出由于之前的翻转,第二个索引处的灯泡被关闭,所以我们将状态改为1状态,这使我们正在寻找的状态为1,同样翻转开关改变了下一个状态的标准我们将搜索。

我在下面写了一段代码片段,这样更容易理解

bool flipped = false;
int ans = 0;
for(int i = 0;i < N;i++){
    if(flipped == false){
        if(A[i] == 0){
            ans++;
            flipped = true;
        }
    }else if(flipped == true){
        if(A[i] == 1){
            ans++;
            flipped = false;
        }
    }
}

这里我使用的翻转变量告诉灯泡是否已被翻转,如果它们被翻转,那么我们将搜索1(在开关上),因为实际上它们因为之前的翻转而为0(关闭)。

答案 1 :(得分:1)

另一个简单的解决方案:

int solve(int A[], int N) {

    int count=0;
    for (int i = 0; i < N;i++) {
        if ((A[i] == 0 && count%2==0)|| (A[i]==1 && count%2==1)) {
            count++;
        }
    }
    return count;

答案 2 :(得分:0)

只有两点需要了解:

  1. 由于在翻转特定开关时会翻转右侧的灯泡,因此从左向右迭代灯泡是有意义的,即从0bulbs.length的索引;并且,

  2. 因为右侧灯泡的状态可以颠倒,所以我们需要知道是将灯泡的状态视为颠倒还是按原样对待。


这是实现以上两点的简短代码。阅读评论,它将非常容易理解:

int count = 0;
boolean flip = false; //Initially we don't flip the states, so flip is false

for(int i = 0; i < bulb.length; i++) {
    //A bulb is ON when:
    //1. The bulb is ON and it is not supposed to be flipped.
    if (bulb[i] == 1 && !flip) continue;

    //2. The bulb is OFF but it is supposed to be flipped.
    if (bulb[i] == 0 && flip) continue;

    //Now the bulb is OFF, so we turn it ON i.e. increment count and
    //invert the flipping condition for the rest of the bulbs on the right.
    count++;
    flip = !flip;
}

return count;

答案 3 :(得分:0)

理解该解决方案的另一种方法是分组,假设我们有[0,0,0]一个开关可以关闭,或者它们全部三个都关闭,所以我们将尝试找到这样的组。如果第一个灯泡打开,我们将不会翻转它。例如,

1 0 1 0 0 0 1 1 0 0

这里有3组零(灯泡关闭)和3组1(灯泡打开)。但是对于第一个1(ON灯泡),我们不必关心。因此,整个一组1 = 2和一组零= 3,因此我们将需要5个开关来打开所有灯泡。

int Solution::bulbs(vector<int> &A) {
    int group_one = 0;
    int group_zero = 0;

    if (A.size() == 0) return 0;

    if (A[0]) group_one++;
    else group_zero++;

    for (int i = 1; i < A.size(); i++) {
       if (A[i] == 0 && A[i - 1] == 1) group_zero++;
       else if (A[i] && A[i-1] == 0) group_one++;
    }
    // For All bulbs are either ON or OFF
    if (group_one && group_zero == 0) return 0;
    if (group_zero && group_one == 0) return 1;

    if (A[0]) group_one -= 1;

    return group_one + group_zero; }