Eno*_*noy 2 java algorithm math list object
我正在做以下编程练习:火车中有多少辆货车?。声明是:
\n\n\n\n\n你坐在一列永久绕圈移动的火车上。火车\n是环形的:头与尾相连,你可以直接从一个\n转到另一个\n。
\n\n每辆马车都有灯。灯的初始状态未知。如果您愿意,您可以打开或关闭它。
\n\n数一下货车的数量!
\n\n您可以根据需要在车厢之间移动。
\n\n限制条件。清点车厢数量后,火车上的灯应处于初始状态。但最终你不需要在你开始的那辆马车里。
\n\n使用已实现的 Train 方法:
\n\n公共布尔 isLightOnInCurrentWagon()
\n\n公共无效开关灯()
\n\n公共无效 goToNextWagon()
\n\n公共无效 goToPreviousWagon()
\n\n火车符号“1 : 0 : 0”表示您有一列有三节车厢的火车。第一辆货车的灯亮着,另外两辆货车的灯熄灭。
\n
首先,我想保留三个整数列表:原始的、交换的和最终的。Original 会按开始时的状态存储灯光。切换将存储原始的补充(切换每辆货车的灯后)。Final 将使灯光保持原始状态(切换回原始状态后)。
\n\nFor example for train: 1:0:1\n\nOriginal: {1,0,1}\nSwitched: {0,1,0}\nFinal: {1,0,1}\n
Run Code Online (Sandbox Code Playgroud)\n\n然而困难在于,我们如何知道火车的头/起点在哪里?
\n\n此外,我尝试了一些基本情况的代码,其中火车只有一节车厢:
\n\nimport java.util.*;\npublic class Solution {\n public int howManyWagons/*\xe2\x9d\x94*/(Train train){\n int haveWeEnded = 0, prev = 0, first = 0, next = 0;\n if(train.isLightOnInCurrentWagon()){\n first = 1;\n }\n System.out.println("first: "+first);\n train.switchLight();\n train.goToNextWagon();\n if(train.isLightOnInCurrentWagon()){\n next = 1;\n }\n System.out.println("next: "+next);\n train.switchLight();\n train.goToPreviousWagon();\n if(first != next){\n train.switchLight();\n train.goToPreviousWagon();\n if(train.isLightOnInCurrentWagon()){\n prev = 1;\n }\n System.out.println("prev: "+prev);\n train.switchLight();\n }\n return prev == next && first != prev && first != next ? 1 : 0;\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n作为测试用例(取自挑战):
\n\nimport org.junit.jupiter.api.Test;\n\nimport java.util.Random;\n\nimport static org.junit.jupiter.api.Assertions.*;\n\nclass SolutionTest extends Train {\n\n Solution sol = new Solution();\n Random rand = new Random();\n\n @Test\n void howManyWagonsCornerCases() {\n\n String repr;\n Train train;\n\n repr = "1";\n train = Train.fromRepr(repr);\n assertEquals(1, sol.howManyWagons(train), repr);\n\n repr = "1 : 0 : 1 : 0 : 0";\n train = Train.fromRepr(repr);\n assertEquals(5, sol.howManyWagons(train), repr);\n\n repr = "1 : 0 : 0";\n train = Train.fromRepr(repr);\n assertEquals(3, sol.howManyWagons(train), repr);\n\n repr = "1 : 1 : 0 : 0 : 1 : 1";\n train = Train.fromRepr(repr);\n assertEquals(6, sol.howManyWagons(train), repr);\n\n repr = "0 : 0 : 0 : 0 : 0";\n train = Train.fromRepr(repr);\n assertEquals(5, sol.howManyWagons(train), repr);\n\n repr = "1 : 1 : 1 : 1 : 1";\n train = Train.fromRepr(repr);\n assertEquals(5, sol.howManyWagons(train), repr);\n\n\n repr = "1 : 0 : 1 : 0 : 0 : 1 : 1 : 0 : 0";\n train = Train.fromRepr(repr);\n assertEquals(9, sol.howManyWagons(train), repr);\n }\n\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n所以当只有一辆马车时,它确实算数。但是我们怎样才能使这个通用呢?因为如果我们有 5 辆货车(第二次测试),如:“1 : 0 : 1 : 0 : 0”,代码输出:
\n\nfirst: 1\nnext: 0\nprev: 0\n
Run Code Online (Sandbox Code Playgroud)\n\n因为它检测到的模式与只有一辆马车一样,所以它返回 1 而不是 5。
\n\n另外,我读过:
\n\n我们如何计算双向链表(循环链表)中的元素,我们不知道初始状态,也不知道 head / tail\xe2\x80\xbd 在哪里
\n\n编辑:使用@Chamika的答案我试图解释创建算法的思维过程是如何的
\n\nimport java.util.*;\n\npublic class Solution {\n public int howManyWagons/*\xe2\x9d\x94*/(Train train){\n boolean end = false;\n int count = 1;\n while(!end){\n // We save the light of the initial wagon to be able to reset it later\n boolean isFirstWagonLightOn = train.isLightOnInCurrentWagon();\n //\xef\xb8\x8f We turn off the light of the initial wagon, to mark \xe2\x9b\xb3 where we started this iteration\n if(train.isLightOnInCurrentWagon()){\n train.switchLight();\n }\n goForward(train,count);\n //If the light is on , we know we are not in the initial wagon, we go to the initial wagon and count it\n if(train.isLightOnInCurrentWagon()){\n goBack(train,count);\n count++;\n //When the light is off \xef\xb8\x8f, we may have go back to the initial position\n }else{\n //We switch the light ,go back\n train.switchLight();\n goBack(train,count);\n //If after going back the wagon light is on , it means we stand inside the end wagon\n if(train.isLightOnInCurrentWagon()){\n end=true;\n }else{\n //If light is off \xef\xb8\x8f, we have not been in the end position yet\n goForward(train,count);\n train.switchLight();\n goBack(train,count);\n count++;\n }\n }\n //Reset end position light\n if(isFirstWagonLightOn != train.isLightOnInCurrentWagon()){\n train.switchLight();\n }\n }\n return count;\n }\n\n public static void goForward(Train train,int count){\n while(count > 0){\n train.goToNextWagon();\n count--;\n }\n }\n public static void goBack(Train train,int count){\n while(count > 0){\n train.goToPreviousWagon();\n count--;\n }\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
记录当前车厢内灯光的状态。candidateWagonCount
然后在从 1 到无穷大(或 到)的循环中查看火车上Integer.MAX_VALUE
是否有车厢。candidateWagonCount
该检查按如下方式进行:
candidateWagonCount
货车前进。如果灯亮了,我们就知道candidateWagonCount
火车上不能有车厢。返回candidateWagonCount
到原来的位置并进入下一个迭代。candidateWagonCount
货车移回我们知道的起点。将灯打开。再次推动candidateWagonCount
货车前进。如果灯现在亮了,我们就知道我们已经回到了起点。candidateWagonCount
因此,火车上一定有车厢。将灯设置为原始状态(打开或关闭)并退出。否则将candidateWagonCount
货车移回起始位置。在我看来,困难在于不知道起点或终点在哪里,因为火车是圆形的,所以没有\xe2\x80\x99t。您也可以决定考虑火车出发的位置。
\n对我来说,挑战在于我们如何知道什么时候已经绕了一整圈。如果我们只是沿着火车的一个方向移动,即使我们认出了我们之前离开的一种灯光模式,我们也不知道我们是否回来了,或者我们来到了一系列新的车厢,恰好有相同的模式。解决方案是在将某个灯关闭和打开后都采取相同的步骤。
\n