문제

무엇 최고의(정지)알고리즘을 결정하는 경우 연결 목록을 주기에 그것은?

[편집]분석의 근사 복잡성을 위해 시간과 공간의 달콤한 너무 답변을 비교할 수 있습 better.

[편집]원래 질문을 해결 노드 outdegree>1,하지만 일부는 그것에 대해 얘기합니다.는 질문가의 라인을 따라 더 많은"최고의 알고리즘을 감지하는 사이클에서 방향 그래프".

도움이 되었습니까?

해결책

두 개의 포인터를 통해 반복 목록하나의 반복을 통해서 두 번의 속도는,그 비교는 자신의 위치를 각 단계입니다.상단의 머리,다음과 같습니다.

node* tortoise(begin), * hare(begin);
while(hare = hare->next)
{
    if(hare == tortoise) { throw std::logic_error("There's a cycle"); }
    hare = hare->next;
    if(hare == tortoise) { throw std::logic_error("There's a cycle"); }
    tortoise = tortoise->next;
}

O(n)는 좋은 당신이 얻을 수 있습니다.

다른 팁

제 조건추적 목록 크기(업데이트 크기 whenenver 노드를 추가하거나 삭제).

루프 검색:

  1. 을 유지할 때 카운터를 통과하는 목록은 크기입니다.

  2. 반면,카운터 초과한 목록의 크기가 가능한 주기입니다.

복잡:O(n)

참고:사이의 비교를 카운터 그리고 목록 크기뿐만 아니라,업데이트 작업 목록의 크기 만들 수 있어야 합 스레드에 안전합니다.

2 포인터*p,*q,시작을 통과하는 링크 목록"LL"모두 사용하여 포인터:

1)포인터 p 삭제됩니다 이전 노드를 각 시간을 가리키는 다음 노드입니다.

2)포인터 q 마다 갈 것입니다에서 앞으로의 방향 방향으로만 있습니다.

태:

1)포인터 p 가 가리키는 null 및 q 를 가리키는 일부 노드:루프는 현재

2)모두를 가리키는 포인터 null:아프가

에 대해 무엇을 사용하여 해시 테이블을 저장을 이미 보 노드(당신이 그들을 보기 위해서는 시작부터 목록)?에서 연습,당신이 얻을 수 있는 가까운 무언가를 O(N).

그렇지 않으면 사용하여 정렬된 힙 대신 해시 테이블을 달성하는 것입니다 O(N 로그(N)).

내가 궁금해 있는 경우 다른 방법으로 보다가 반복적으로 채우는 배열을 전달하고 확인하는 경우에는 현재 노드에 이미 존재하는 배열을...

콘라드 루돌프의 알고리즘을 작동하지 않을 경우주기지 않을 가리키는 시작이다.다음과 같은 목록에 그것을 만들 것입니다 무한 루프:1->2->3->2.

DrPizza 의 알고리즘은 확실히 갈 수있는 방법입니다.

이 경우에는 OysterD 의 코드는 가장 빠른 것입니다 솔루션(정점을 색칠)

는 것은 정말 놀라게 나입니다.나의 솔루션에서 가장 두를 통과한 목록(는 경우에 마지막 노드에 연결하는 끝에서 두 번째 주),그리고 일반적인 케이스(더 루프)를 만들 것입니다 하나만 전달합니다.없이 해시 메모리 할당,etc.

이 경우에는 OysterD 의 코드는 가장 빠른 것입니다 솔루션(정점을 색칠)

는 것은 정말 놀라게 나입니다.나의 솔루션에서 가장 두를 통과한 목록(는 경우에 마지막 노드에 연결하는 끝에서 두 번째 주),그리고 일반적인 케이스(더 루프)를 만들 것입니다 하나만 전달합니다.없이 해시 메모리 할당,etc.

그렇습니다.나는 것으로 나타났을 정립지 완벽하고 고쳐니다.나는 여전히 믿는 영리한 해싱 더 빠르게 수행될 수 있습–에 의해 머리입니다.내가 믿는 알고리즘 최고의 솔루션,하지만.

단 밑줄 내 포인트:이 vertec 색상은 사용을 감지하는 사이클에서 종속성으로 현대적인 쓰레기 수집가는 이렇게 거기는 매우 실제 활용 사례에 대한니다.그들이 주로 사용 비트 플래그를 수행하 색칠합니다.

당신이 방문하는 모든 노드를 결정한다.이 수행할 수 있습을 재귀적으로.당신을 중지 방문이 이미 방문하는 노드가 필요 플래그를 말하고'이미 많이 방문한'.이 코스의 제공하지 않습니다.그래서 대신의 비트 플래그를 사용,번호입니다.에서 시작 1.체크에 연결된 노드 표시으로 이들 2 과 재귀적으로 사용될 때까지 네트워크가 덮여있다.면을 때 검사하는 노드가 발생할 노드에 있는 하나 이상의 보다 적은 현재 노드에,당신은 사이클.사이클 길이 주어진에 의해 차이가 있습니다.

두 개의 포인터는 초기화되의 목록입니다.하나의 포인터가 전달되면 각 단계에서,그리고 다른 전달은 두 번에서 각 단계입니다.경우 빠르게 포인터를 충족하는 느린이 다시 하나 루프가 있다는 목록에 있습니다.가 없다 그렇지 않으면 반복하는 경우 빠른 하나의 끝에 도달 목록입니다.

아래의 예제 코드는 구현에 따라 이 솔루션입니다.빠르게 포인터가 pFast 고,느리게 하나 pSlow.

bool HasLoop(ListNode* pHead)
{
    if(pHead == NULL)
        return false;


    ListNode* pSlow = pHead->m_pNext;
    if(pSlow == NULL)
        return false;


    ListNode* pFast = pSlow->m_pNext;
    while(pFast != NULL && pSlow != NULL)
    {
        if(pFast == pSlow)
            return true;


        pSlow = pSlow->m_pNext;


        pFast = pFast->m_pNext;
        if(pFast != NULL)
            pFast = pFast->m_pNext;
    }


    return false;
}

이 솔루션을 사용할 수 있에 내 블로그.더 많은 문제 논의에서 이 블로그:는 무엇입 항목을 노드에 있을 때 주기/루프에서나요?

"해킹"솔루션(작동해야에서는 C/C++):

  • 트래버스 목록을 설정은 마지막 비 next 포인터 1.
  • 는 경우 요소 찾기와 플래그 지정된 포인터--true 를 반환하고의 첫 번째 요소는 주기입니다.
  • 을 반환하기 전에,리셋 포인터를,그래도 나는 믿을 참조할 것이 작품으로도 플래그 지정된 포인터입니다.

시간 복잡도는 2n.처럼 보인다 사용하지 않는 어떤 시간적 변수입니다.

이 솔루션을 사용하여 해시 테이블(다만 목록이 실제로)저장하는 포인터.

def hash_cycle(node):
    hashl=[]
    while(node):
        if node in hashl:
            return True
        else:
            hashl.append(node)
            node=node.next
    return False

def has_cycle(머리):counter=set()

while head is not None:
    if head in counter:
        return True
    else:
        counter.add(head)
        head = head.next
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top