2013-05-31 2 views
-1

난 그냥 워밍업을하고 있었는데, 나는이 우연히 :신비한 stackoverflow 오류?

http://codingbat.com/prob/p145416

세 가지 방법의 차이는 내가 재귀 호출에서 시작 매개 변수에 추가하는 방법입니다.

처음에는 두 번째 함수를 사용하여 해결했지만 나에게 유명한 stackoverflow 오류가 발생했습니다. 첫 번째는 나에게 stackoverflow 오류를주지 않는다. 이 사이트에 문제가 있습니까? 아니면 1과 2의 차이가 있습니까? 즉, Java 언어의 미묘한 부분입니까?

public boolean groupSum(int start, int[] nums, int target) { 
    if (start >= nums.length) 
     return (target == 0); 

    return groupSum(start+1, nums, target - nums[start]) || groupSum(start+1,  
     nums, target); 
} 

------------ 유동 오류 원인이 위에 스택 --------------

public boolean groupSum(int start, int[] nums, int target) { 
    if (start >= nums.length) 
     return (target == 0); 

    return groupSum(start++, nums, target - nums[start]) || groupSum(start++,  
     nums, target); 
} 

public boolean groupSum(int start, int[] nums, int target) { 
    if (start >= nums.length) 
     return (target == 0); 

    return groupSum(++start, nums, target - nums[start]) || groupSum(++start,  
     nums, target); 
} 
+0

신비한 stackoverflow 오류가 없습니다. 단지 재귀 적 메서드가 중단되지 않았다는 것을 의미합니다. 왜? 아마도 틀린 디자인의 기본 케이스 일 겁니다. 또한 Java *에서만이 문제가 발생한다고 말하지 마십시오. 다른 프로그래밍 언어에서도 발생할 수 있습니다. –

+0

또한 나는 O (2^n)의 복잡성을 가지고 있기 때문에 이러한 기능이 얼마나 비속적인지 알게됩니다. 나는 인터뷰를 위해 워밍업을하고 있으며 재귀와 연습이 필요하다. – LLL

+0

세 함수 모두 동일한 기본 사례를 사용합니다. 그것들은 단지 내가 시작하는 방법에있어서 차이가 있습니다. 나는 그 질문을 분명히 할 것이다. – LLL

답변

1

++start는 (알려진 사전 증가)는 start+1으로 평가됩니다. start++ (증분이 AFTER 평가와 같이 후 증가로 알려짐)은 start으로 평가됩니다. 두 변수 모두 변수의 값을 start+1으로 평가의 부작용으로 설정합니다. 따라서 start++을 호출하면 start을 메서드의 다음 호출에 전달합니다.이 메서드는 다음 호출에 start을 전달합니다. 기본 사례에 도달하지 않고 무한 반복됩니다.

+0

++ start를 사용하면 stackoverflow가 발생합니다.나는 처음에는 같은 것을 생각했다. 사이트의 버그 일 수 있습니다. – LLL

+0

@LLL 나는 그것을 믿지 않는다. (나는 또한 사이트의 버그 일 수 있다고 생각하지 않는다. 당신과 같은 컴파일러를 사용하고있을 것이다.) – Patashu

+0

나는 사이트에 대한 링크를 당신에게 주었다;) 나는 정말 버그를 찾는 데 능숙하다. 그것은 저주입니다. – LLL

4

이것은 아주 미세한 버그입니다. 이 재귀 호출에서보세요 : 첫 번째 매개 변수로 start++을 전달하는

groupSum(start++, nums, target - nums[start]) 

공지 사항.

  • 증가 start, 다음
  • 돌아 start 사용하는 값을 가지고 : 이것은 다음을 수행 접미사 ++ 연산자를 사용합니다. 즉

,이 후, start + 1 수 재귀 호출에 start의 이전 값을 전달하는 start지역 사본을 업데이트합니다. 즉, start은 호출간에 변경되지 않으므로 기본 사례가 트리거되지 않으므로 스택 오버플로가 발생합니다. 함수의 맨 위에 System.out.println 문을 넣어이를 확인할 수 있습니다.

여기에는 다른 문제가있을 수 있지만이 문제가 귀하의 범인이라고 생각합니다.

희망이 도움이됩니다.

+0

에 대한 최신 코멘트를 참조하십시오. 왜 이것이 ++ 시작에 실패하는지 설명하지 않습니다. – LLL

+0

@LuiggiMendoza 사실이 아닙니다. ++ start는 start + 1을 리턴하므로 무한대로 재귀해서는 안됩니다. – Patashu

+0

@Patashu 네 말이 맞아. 지금 SOE를주는'++ start'의 원인을 평가합니다. –