อัลกอริทึมเพื่อพิจารณาว่ามีลูปอยู่ในรายการที่เชื่อมโยงหรือไม่

ดังนั้นฉันจึงเพิ่งพบอัลกอริทึมเพื่อพิจารณาว่ามีวงจรอยู่ในรายการที่เชื่อมโยงหรือไม่ รหัสมีดังนี้:

public boolean hasCycle(ListNode head) {
    if (head == null) {
        return false;
    }
    ListNode fast = head;
    ListNode slow = head;
    while (fast != null) {
        if (fast.next == null) {
            return false;
        }
        if (fast.next == slow) {
            return true;
        }
        fast = fast.next.next;
        slow = slow.next;
    }
    return false;
}

เมื่อพยายามพิสูจน์ความถูกต้องของอัลกอริทึมนี้ ฉันเกิดแนวคิดขึ้นมา: สมมติว่าเส้นรอบวงของวงจรคือ "a" เวลาที่ผ่านไปก่อนที่พอยน์เตอร์สองตัวจะพบกันคือ "t" เนื่องจากความเร็วของโหนด "เร็ว" เคลื่อนที่เร็วเป็นสองเท่าของโหนด "ช้า" เราจึงสามารถได้ความสัมพันธ์ทางคณิตศาสตร์:

2t mod a = เสื้อ mod a

ตอนนี้ "a" เป็นค่าคงที่แทนเส้นรอบรูป และ "t" อาจเป็น 1,2,3.... แล้ว ฉันจะพิสูจน์ได้อย่างไรว่าไม่ว่าค่า "a" จะเป็นเท่าใด เราก็สามารถหา "t" ดังกล่าวได้เสมอ ว่าสมการข้างต้นแก้ได้?


person Zhengyang Fang    schedule 06.10.2016    source แหล่งที่มา
comment
stackoverflow.com/q/2936213/1835769   -  person displayName    schedule 06.10.2016
comment
สมการจะถูกต้องหรือไม่หากวงจรไม่เริ่มต้นที่โหนดแรก? เช่น 1->2, 2->3, 3->4, 4->5, 5->3, รอบ = {3,4,5,3}   -  person shole    schedule 06.10.2016
comment
t = 0 mod a ใด ๆ แก้ 2t = t mod a คุณต้องมี t >= s ด้วย โดยจะต้อง s ขั้นตอนเพื่อเข้าสู่วงจร   -  person Matt Timmermans    schedule 06.10.2016
comment
@MattTimmermans อืม...ฉันคิดว่าบางทีมันอาจจะเหมือนเดิมหลังจากที่ฉันคิดสักพัก: 2t -s = t-s (a) ดังนั้น 2t = t (a) ไม่แน่ใจ   -  person shole    schedule 06.10.2016
comment
@shole คุณต้องมีทั้งสองเงื่อนไข หากต้องใช้ 13 ขั้นตอนเพื่อเข้าสู่วงจรที่มีความยาว 10 พอยน์เตอร์จะพบกันที่ t=20 และ t=30 แต่ไม่ใช่ t=10   -  person Matt Timmermans    schedule 06.10.2016
comment
@MattTimmermans ใช่คุณพูดถูก   -  person shole    schedule 06.10.2016


คำตอบ (2)


คุณมาถูกทางแล้ว! คำแนะนำ: จะเกิดอะไรขึ้นกับสูตรของคุณหลังจากการวนซ้ำ a

person Aasmund Eldhuset    schedule 06.10.2016

สมมติว่าตัวชี้ทั้งสองเริ่มต้นที่จุดเดียวกันภายในวงจร (และไม่นับเป็นการประชุม)

2t = t (a)

=> 2t - t = 0 (a)

=> t = 0 (a)

ซึ่งหมายความว่าที่ t = a*k พอยน์เตอร์ทั้งสองจะบรรจบกันที่จุดเริ่มต้นหลังจากเวลาที่ผ่านไปเป็นทวีคูณของความยาวรอบ

มันเป็นจริงสำหรับ a >= 2 ทั้งหมด เพราะเมื่อเวลาเท่ากับ k*a สำหรับ k>1 ทั้งหมด ตัวชี้ที่ช้าจะทำงานนาน k รอบอย่างแน่นอน ในขณะที่ตัวชี้เร็วจะทำงานเร็วขึ้นสองเท่า ดังนั้นจึงทำงานนาน 2,000 รอบ แต่ยังคงพบกันที่จุดเดียวกันซึ่งก็คือ จุดเริ่มต้น

person shole    schedule 06.10.2016
comment
ฉันหลงทางในขั้นตอนที่สองของคุณ : ( คุณจะได้ 2t - t = 0 (a) จาก 2t = t (a) ได้อย่างไร? - person Zhengyang Fang; 10.10.2016
comment
แค่ลบ t%a ทั้งสองข้างเหรอ? - person shole; 11.10.2016