简体   繁体   English

有人可以解释一下下面的代码如何工作吗

[英]Could somebody please explain me how the following code actually works

Could somebody please explain me how the following code actually works. 有人可以向我解释以下代码的实际工作方式。

Problem: You have 64 doors in a row that are all initially closed. 问题:您连续有64扇门,这些门最初都是关闭的。 You make 64 passes by the doors. 您在门旁经过了64次。 The first time through, you visit every door and toggle the door (if the door is closed, you open it; if it is open, you close it). 第一次访问时,您访问每个门并切换门(如果门是关闭的,则将其打开;如果门是打开的,则将其关闭)。 The second time you only visit every 2nd door (door #2, #4, #6, ...). 第二次您仅访问第二个门(#2,#4,#6,...)。 The third time, every 3rd door (door #3, #6, #9, ...), etc, until you only visit the 64th door. 第三次,每隔第三个门(3号门,6号门,9号门...)等等,直到您只访问第64个门。

The following code I found works, but I'd like to know what exactly is happening. 我发现以下代码可以正常工作,但是我想知道到底发生了什么。 I don't understand the loop. 我不明白循环。

public class doors {
public static void main(String args[]) {
    // assume true=open, false=closed. Doors will all default to closed.
    boolean[] doors = new boolean[64];
    for (int i=0; i<64; i++) {
        for (int j=i; j<64; j=j+i+1) {
            doors[j] = !doors[j];
        }
    }
    // at the end, print out all the doors that are closed
    System.out.println("These doors are opened:");
    for (int i=0;i<64;i++){
        if (doors[i]) {
            // printing out i+1 to negate the zero-indexing
            System.out.println(i+1);
        }
    }
}
}

Assuming that you know how for loops works, still, lets take a look at the following example: 假设您知道for loops工作原理,那么让我们看一下以下示例:

First assume that all of the doors are closed and close means false f , open means true t . 首先,假设所有门均已关闭,并且关闭表示false f ,打开表示true t For a simpler understanding we are also assuming that, total number of doors = 4 . 为了更简单地理解,我们还假设门总数= 4

index       :     0       1       2       3
              +-----+ +-----+ +-----+ +-----+
begin       : |  f  | |  f  | |  f  | |  f  | // say all doors closed
              +-----+ +-----+ +-----+ +-----+
door number :    1       2       3       4

Now 现在

 for (int i=0; i<4; i++) { // our example has 4 doors instead of 64
        // first iteration of outer loop, i = 0
        for (int j=i; j<4; j=j+i+1) {
            // as i = 0, j = 0 too
            // and j = j+i+1 = j + 0 + 1 = j +1 
            // so j will increment by 1
            // hence, j < 4 means the loop will rotate 4 (j = 0 to 3) times 
            doors[j] = !doors[j]; // this line do the trick, See bellow for details.
        }
    }

The doors[j] = !doors[j]; doors[j] = !doors[j]; toggles the current state. 切换当前状态。 How? 怎么样? suppose the doors[j] contains false means door is closed, then !doors[j] change the value false to true means closed to open! 假设door doors[j]包含false表示门已关闭,然后!doors[j]将值false更改为true意味着已关闭以打开! Ta da, that's what we want! 塔达,这就是我们想要的!

   index(value of j) :    0       1       2       3
                       +-----+ +-----+ +-----+ +-----+
after 1st iteration  : |  t  | |  t  | |  t  | |  t  |
                       +-----+ +-----+ +-----+ +-----+
         door number :    1       2       3       4

All four doors opens! 全部四个门打开!

Now, for the 2nd iteration of outer loop, 现在,对于外循环的第二次迭代,

 for (int i=0; i<4; i++) { // our example has 4 doors instead of 64
        // 2nd iteration of outer loop, i = 1
        for (int j=i; j<4; j=j+i+1) {
            // as i = 1, j = 1 too
            // and j = j+i+1 = j + 1 + 1 = j + 2 
            // so j will increment by 2
            // hence, j < 4 means the loop will rotate 2 (j = 1 and j = 3) times 
            doors[j] = !doors[j]; 
        }
    }

So, 所以,

   index(value of j) :    0       1       2       3
                       +-----+ +-----+ +-----+ +-----+
after 2nd iteration  : |  t  | |  f  | |  t  | |  f  |
                       +-----+ +-----+ +-----+ +-----+
         door number :    1       2       3       4

Only 2 and 4 number doors are closed! 只有2个和4个数字门关闭! Yes, we are on right track! 是的,我们步入正轨!

Now you clearly understand that in the third iteration of outer loop, j will start with value 2 and increment by 3 , means only door 3 will be toggled! 现在您清楚地了解到,在外循环的第三次迭代中, j将以值2开头并以3递增,这意味着仅门3将被切换!

   index(value of j) :    0       1       2       3
                       +-----+ +-----+ +-----+ +-----+
after 3rd iteration  : |  t  | |  f  | |  f  | |  f  |
                       +-----+ +-----+ +-----+ +-----+
         door number :    1       2       3       4

Hope this will help you to understand how the problem is solved by this code for 64 doors! 希望这将帮助您了解此代码如何解决64门的问题!

The final (4th) iteration will makes all the door, looks like: 最终的(第4次)迭代将使所有的门都看起来像:

   index(value of j)   :    0       1       2       3
                         +-----+ +-----+ +-----+ +-----+
after final iteration  : |  t  | |  f  | |  f  | |  t  |
                         +-----+ +-----+ +-----+ +-----+
         door number   :    1       2       3       4

First job: number the doors 1 - 64. Having them zero based messes up the mathematics. 第一项工作:给1至64的门编号。让它们从零开始就搞乱了数学。

A door will remain open if, and only if, the number of factors in its number is odd. 当且仅当门中的数量为奇数时,门才会保持打开状态。

That is only true for perfect squares, as any other number has an even number of factors. 这仅适用于完美平方,因为任何其他数均具有偶数个因子。 (For example, 10 has 1, 10, 2, and 5. But 25 has 1, 25, and 5). (例如,10具有1、10、2和5。而25具有1、25和5)。

So the doors that remain open are 1, 4, 9, 16, 25, 36, 49, and 64. 因此,保持打开状态的门是1、4、9、16、25、36、49和64。

So all you need to do to get the answer is to iterate through the perfect squares, and that's O(N). 因此,要获得答案,您需要做的就是遍历完美的平方,这就是O(N)。

The way your code will figure this out is abysmally inefficient as it's O(N * N). 您的代码将解决这一问题的方式非常低效,因为它的O(N * N)。 Your code works by repeatedly traversing the door set. 您的代码通过反复遍历门组而起作用。 The key expression is j=j+i+1 which bypasses an increasingly large number of doors. 关键表达式是j=j+i+1 ,它绕开了越来越多的门。 doors[j] = !doors[j]; changes the door state. 更改门的状态。

Try to recode in O(N) using the perfect squares approach. 尝试使用完美平方方法重新编码O(N)。 That will impress your professor. 那会让你的教授印象深刻。

if you mean you don't understand this loop: 如果您不了解此循环,请执行以下操作:

 for (int i=0; i<64; i++) {
    for (int j=i; j<64; j=j+i+1) {
        doors[j] = !doors[j];
    }
}

This is the most straightforward solution. 这是最直接的解决方案。 In the outer loop, i represents the step (so you have 64 steps altogether), i also represents number of door to skip (how many door you jump) to toggle. 在外部循环中,i代表要执行的步骤(因此,您总共有64个步骤),i代表要跳过的门数(要跳多少门)。 So in the loop 0, you skip no door to toggle, in the loop 1, you skip 1 door, in the loop number 2, you skip 2 door each time,...and so on. 因此,在循环0中,您不跳过任何门,在循环1中,您跳过1门,在循环编号2中,您每次都跳过2门,...依此类推。 The inner loop will find the actual doors to toggle and store in index j. 内循环将找到要切换的实际门并将其存储在索引j中。 Since you will skip i doors in step number i so you will start from i up to 64 and each time increase the index by i+1 (equivalent to skip i doors). 由于您将在第i步中跳过i门,因此您将从i开始直到64,并且每次将索引增加i + 1(相当于跳过i门)。 Hope you understand. 希望你能理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM