>
나는 벽을 오르는 달팽이에 대해 운동을하고 있는데 정상에 도달하는 데 며칠이 걸리는지 계산해야합니다. 나는 이미 알고리즘을 수행했으며 예상되는 출력을 제공하지만 너무 오래 걸립니다. 입력 사례, 기본적으로 코드가 수행해야 할 작업은 NMTN = 하루에 몇 미터를 등반합니까? M = 밤에 몇 미터를 넘어서고 T = 벽의 길이는 무엇입니까?이 코드는 도움이 될 것입니다. 내 코드 PD는 이미 작동하지만 너무 느립니다

      int distance=0;
       int[] up = { 2, 5 ,100};
       int[] down= { 1,1 ,99};
       int[] Top = {5,6 ,1000000000};
       int days = 0;
       for (int i = 0; i < up.length; )
       {
           distance += up[i];
           if (Top[i] <= distance)
           {
               days++;
               System.out.println(days);
                i++;
               days = 0;
               distance = 0;
           }
           else
           {
               distance -= down[i];
               days++;
           }
       }  

출력은 다음이다 : 사례 1 : 4 사례 2 : 2 사례 3 : 999999901

  • 답변 # 1

    코드를 단순화하기 위해 코드를 리팩터링 할 수 있습니다. 이것이 Wikipedia가 리팩토링을 설명하는 방법입니다 :

    와이즈 비즈

    그래서 우리는 마이크로 리팩터링을 적용 할 것입니다.

    먼저,

    Code refactoring is the process of restructuring existing computer code—changing thefactoringwithout changing its external behavior. Refactoring improvesnonfunctionalattributes of the software.Advantages include improved code readability and reduced complexity; these can improve source-code maintainability and create a more expressive internal architecture or object model to improve extensibility.Typically, refactoring applies a series of standardised basicmicro-refactorings, each of which is (usually) a tiny change in a computer program's source code that either preserves the behaviour of the software, or at least does not modify its conformance to functional requirements.

    내부의 두 문장  절을 뒤집을 수 있습니다.

    else
    
    

    그러면 } else { days++; // Statement moved up distance -= down[i]; }  블록과 if   else 로 시작하는 블록 외부로 이동할 수 있습니다.

    days++;
    
    

    와이즈 비즈 이후  루프는 for (int i = 0; i < up.length;) { distance += up[i]; days++; // Statement moved outside if (Top[i] <= distance) { System.out.println(days); i++; days = 0; distance = 0; } else { distance -= down[i]; } } 를 수정하지 않습니다 루프 내부의 코드가 for 를 변경하지 않는 한 영구 루프처럼 작동합니다. . 따라서 i 를 변경하면 영구 루프를 추가하고 끊을 수 있습니다. . 결과는 아무것도 변경되지 않았지만 다음 리팩토링 세트를 준비합니다.

    i
    
    

    와이즈 비즈 이후  문은 영원히 반복되는 유일한 방법입니다. i 이전의 코드를 이동할 수 있습니다.  루프 외부 (즉, 이후)로.

    for (int i = 0; i < up.length;) {
        for (;;) {   // Forever-loop
            distance += up[i];
            days++;
            if (Top[i] <= distance) {
                System.out.println(days);
                i++;
                days = 0;
                distance = 0;
                break;   // Break out, since we changed i
            } else {
                distance -= down[i];
            }
        }
    }
    
    

    와이즈 비즈 이후  그리고 break   break 로 초기화됩니다  외부 루프 이전에 int distance = 0; int days = 0; for (int i = 0; i < up.length;) { for (;;) { distance += up[i]; days++; if (Top[i] <= distance) { break; } else { distance -= down[i]; } } System.out.println(days); // Moved outside forever-loop i++; // Moved outside forever-loop days = 0; // Moved outside forever-loop distance = 0; // Moved outside forever-loop } 로 다시 초기화되었습니다.  루프가 끝날 때 루프의 시작 부분에서 대신 할 수 있으며 거기서 선언 할 수 있습니다. 우리는 또한 days 를 이동할 수 있습니다   distance 에  루프.

    0
    
    

    우리는 이제 0 를 증가시키는 두 문장에 대해 반대 연산을 할 것입니다.  그리고 i++  forever-loop 내부에서, 즉 루프 전과 루프 끝에서 두 가지 문장을 수행하십시오.

    for
    
    

    for (int i = 0; i < up.length; i++) { // i++ moved here int distance = 0; // Moved to top of loop and declared here int days = 0; // Moved to top of loop and declared here for (;;) { distance += up[i]; days++; if (Top[i] <= distance) { break; } else { distance -= down[i]; } } System.out.println(days); } 의 초기화  그리고 distance  영구 루프 이전에 수행 된 증분과 결합 될 수 있습니다. 또한 days 이후  루프를 종료하고 for (int i = 0; i < up.length; i++) { int distance = 0; int days = 0; distance += up[i]; // Moved here days++; // Moved here for (;;) { if (Top[i] <= distance) { break; } else { distance -= down[i]; } distance += up[i]; // Also moved here days++; // Also moved here } System.out.println(days); } 가 필요 없습니다.  더 이상.

    distance
    
    

    days  는 forever 루프 내에서만 사용되므로 선언을 루프로 옮길 수 있습니다. break 의 업데이트  영구 루프의 세 번째 부분으로 이동할 수 있습니다. 와이즈 비즈  명령문은 영구 루프의 맨 위에 있으므로 대신 루프 조건이되어 영구 루프를 일반 else 로 변경할 수 있습니다.  루프.

    for (int i = 0; i < up.length; i++) {
        int distance = up[i];   // Combined =0 with +=up[i]
        int days = 1;           // Combined =0 with ++
        for (;;) {
            if (Top[i] <= distance)
                break;
            distance -= down[i];   // else clause eliminated
            distance += up[i];
            days++;
        }
        System.out.println(days);
    }
    
    

    현재 코드가 얼마나 간단한 지 확인하고 코드의 논리를 변경하지 않았습니다. 방금 옮겼습니다.리팩터링

    내부 루프는 세 번째 사용 사례에서 거의 10 억 번 반복해야하므로 성능 문제가 발생하지만 이제 간단한 distance 를 볼 수 있습니다.  루프를 반복 할 때 실제로계산할 수 있습니다.

    해당 공식을 만들려면 일반 루프를 고려하십시오.

    distance
    
    

    반복되는 횟수는 몇 번입니까? if 를 추가해야합니다  총 for   for (int i = 0; i < up.length; i++) { int days = 1; for (int distance = up[i]; distance < Top[i]; distance += up[i] - down[i]) { days++; } System.out.println(days); } 까지 시간   for 에 도달 그래서 그것은 for (int value = start; value < stop; value += step) 를 의미합니다 .

    step 인 경우   x 의 정확한 배수가 아닙니다 항상 반올림해야하므로 value   stop 가 될 것입니다 . 정수 수학을 사용하면 x = (stop - start) / step 를 추가하면됩니다.  나누기 전에 정수 나누기가 결과를 자르기 때문에 다음 공식이 나타납니다. stop - start

    루프에 적용하면 다음과 같은 결과를 얻습니다.

    step
    
    

    변수 value 에 결과를 할당 할 필요가 없으므로  더 이상 코드는 다음과 같습니다.

    >= stop
    
    

    출력

    step - 1
    
    

    결과가 즉시 계산됩니다. 지체하지 마십시오.

  • 답변 # 2

    작은 수학을 사용하여 닫힌 수식을 만들 수 있습니다.

    x = (stop - start + step - 1) / step
    
    

    x = (stop - start + step - 1) / step x = (Top[i] - up[i] + (up[i] - down[i]) - 1) / (up[i] - down[i]) x = (Top[i] - down[i] - 1) / (up[i] - down[i]) days = 1 + x days = 1 + (Top[i] - down[i] - 1) / (up[i] - down[i])

  • 이전 javascript - 이름이 같은 라디오 버튼의 값을 재설정하거나 선택 해제하는 방법
  • 다음 linux - Ubuntu 응용 프로그램 시작 명령에서 실행 된 프로그램에서 이미지를 저장하는 방법