[劍指offer]62.圓圈中最後剩下的數字

62.圓圈中最後剩下的數字

題目python

0,1,...,n-1這n個數字排成一個圓圈,從數字0開始,每次從這個圓圈裏刪除第m個數字。求出這個圓圈裏剩下的最後一個數字。指針

例如,0、一、二、三、4這5個數字組成一個圓圈,從數字0開始每次刪除第3個數字,則刪除的前4個數字依次是二、0、四、1,所以最後剩下的數字是3。code

方法一 環形鏈表模擬圓圈

思路:用head找要被刪除的元素,用temp的指針指向head。當找到該元素時,令head=head.next,temp.next=head將該元素刪除。內存

class Solution:
    def lastRemaining(self, n: int, m: int) -> int:
        head = temp = ListNode(0)
        for i in range(1, n):
            temp.next = ListNode(i)
            temp = temp.next
        temp.next = head
        while temp.next != temp:
            for i in range(m-1):
                head = head.next
                temp = temp.next
            head = head.next
            temp.next = head
        return temp.val

結果:超時rem

方法二 環形列表

思路:與鏈表相似,本身定義一個列表arr=[0, 1, ..., N-1],每次從i開始計數,數到第m個值將其刪除。最後返回列表中僅存的元素。數學

用%操做使得列表循環遍歷。io

代碼ast

class Solution:
    def lastRemaining(self, n: int, m: int) -> int:
        arr = [i for i in range(n)]
        i = 0
        size = n
        while size > 1:
            del_index = (i+m-1) % size
            arr.remove(arr[del_index])
            size -= 1
            i = del_index
        return arr[0]

結果:超時class

方法三 數學

思路:設從0開始計數,共n我的,數到m個依次出局,最後剩下的人編號設爲f(n,start=0)。第一次出局的人編號爲(m-1)%n,記爲k。List

第二次從k+1開始數,即f(n-1, start=k+1)=f(n, start=0)。

又由於f(n-1, start=k+1)=(f(n-1, start=0)+k+1)%n。

有f(n-1, start=k+1)這個中間橋樑,能夠推出f(n, start=0)=(f(n-1, start=0)+k+1)%n。即 (f(n)=f(n-1)+m)%n.

代碼

class Solution:
    def lastRemaining(self, n: int, m: int) -> int:
        if n < 1 or m < 1:
            return None
        res = 0
        for i in range(2, n+1):
            res = (res + m) % i 
        return res

結果

執行用時 :84 ms, 在全部 Python3 提交中擊敗了82.30%的用戶 內存消耗 :13.6 MB, 在全部 Python3 提交中擊敗了100.00%的用戶

相關文章
相關標籤/搜索