[Code] 閑聊判圈算法

在LeetCode上看到一道題 #141

Given a linked list, determine if it has a cycle in it.

 Definition for singly-linked list.   
  class ListNode(object):  
     def __init__(self, x):  
         self.val = x  
         self.next = None  

如何確定鏈表是否有環(huán)呢?

Floyd判圈算法
假設(shè)龜兔從同一起點(diǎn)(鏈表的起始位置)出發(fā),如果該鏈表有環(huán),當(dāng)兔子和烏龜均進(jìn)入后,必定兔子會(huì)在領(lǐng)先烏龜一圈后與烏龜在鏈表的環(huán)中相遇。所以可以用以下代碼判斷鏈表是否有環(huán)。其中slow的起始位置為head,每次移動(dòng)一步;fast的起始位置也為head,每次移動(dòng)兩步,當(dāng)兩者相遇時(shí)即說明該鏈表有環(huán)。

def hasCycle(self, head):
    try:
        slow = head
        fast = head.next
        while slow is not fast:
            slow = slow.next
            fast = fast.next.next
        return True
    except:
        return False

wiki上的python代碼

def floyd(f, x0):
     tortoise = f(x0)       # f(x0) is the element/node next to x0.
     hare = f(f(x0))
     while tortoise != hare:
         tortoise = f(tortoise)
         hare = f(f(hare))
         if (tortoise == hare):
            return True
     return False

那么,如何判斷環(huán)的長(zhǎng)度呢?

首先要確定鏈表中有環(huán)。

假設(shè)環(huán)起始的位置距離鏈表起始距離為m,而環(huán)的長(zhǎng)度為λ,第一次相遇點(diǎn)距離環(huán)的起點(diǎn)距離為k。則第一次相遇時(shí)烏龜走過的距離ν = m + λ * a + k, 兔子走過的距離2ν = m + λ * b + k。所以ν = (b-a) * λ 為環(huán)長(zhǎng)度的倍數(shù)。

此時(shí)將兔子抓回起點(diǎn)命令其以和烏龜同樣的速度行走,而烏龜則在原地繼續(xù)以之前的速度行走。當(dāng)兔子的行走距離為m(即走到環(huán)的起點(diǎn))時(shí),烏龜走了ν + m,而由于ν為環(huán)長(zhǎng)度的倍數(shù),所以此時(shí)烏龜也走在環(huán)的起點(diǎn),即兔子和烏龜相遇在環(huán)的起點(diǎn)。

當(dāng)然還有更簡(jiǎn)便的方法,當(dāng)兩者相遇后,命令烏龜靜止不動(dòng),兔子降速為每次前進(jìn)一步,當(dāng)兔子再次遇見烏龜時(shí),它比烏龜多跑的距離就是環(huán)的長(zhǎng)度。

求環(huán)的長(zhǎng)度

def floyd(f, x0):

    tortoise = f(x0) # f(x0) is the element/node next to x0.
    hare = f(f(x0))
    while tortoise != hare:
        tortoise = f(tortoise)
        hare = f(f(hare))

    # 方法一、烏龜回到原點(diǎn),兔子降速(與兔子回原點(diǎn)降速相同)    
    m = 0
    tortoise = x0
    while tortoise != hare:
        tortoise = f(tortoise)
        hare = f(hare)   # Hare and tortoise move at same speed
        m += 1
 
    # 方法二、烏龜靜止不動(dòng),兔子降速每次前進(jìn)一步
    lam = 1
    hare = f(tortoise)
    while tortoise != hare:
        hare = f(hare)
        lam += 1
 
    return lam, m
習(xí)得龜兔同跑的判圈算法后,來看一下LeetCode #202

Write an algorithm to determine if a number is "happy".

A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.

"happy數(shù)"的含義為:將一個(gè)數(shù)字的每位平方后相加,相加后的數(shù)繼續(xù)進(jìn)行每位平方后相加,如此循環(huán),當(dāng)相加到最后的數(shù)字始終為1時(shí),即為"happy數(shù)"。

Example: 19 is a happy number

1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

Python解決方案:

def digitSquareSum(n):
    sum, tmp = 0, 0
    while n:
        tmp = n % 10
        sum += tmp * tmp
        n /= 10
    return sum


def isHappy(n):
    slow = digitSquareSum(n)
    fast = digitSquareSum(digitSquareSum(n))
    while slow != fast:
        slow = digitSquareSum(slow)
        fast = digitSquareSum(digitSquareSum(fast))
    if slow == 1:
        return True
    else:
        return False
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容