面試題62. 圓圈中最後剩下的數字(約瑟夫環)

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

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

 

示例 1:

輸入: n = 5, m = 3
輸出: 3
示例 2:

輸入: n = 10, m = 17
輸出: 2
 

限制:

1 <= n <= 10^5
1 <= m <= 10^6

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

遞推方法的代碼:

class Solution {
public:
    int lastRemaining(int n, int m) {
    int s=0;
    for(int i=2;i<=n;i++)
        s=(s+m)%i;
    return s;
    }
};

官方解釋思路:

思路

題目中的要求可以表述爲:給定一個長度爲 n 的序列,每次向後數 m 個元素並刪除,那麼最終留下的是第幾個元素?

這個問題很難快速給出答案。但是同時也要看到,這個問題似乎有拆分爲較小子問題的潛質:如果我們知道對於一個長度 n - 1 的序列,留下的是第幾個元素,那麼我們就可以由此計算出長度爲 n 的序列的答案。

算法

我們將上述問題建模爲函數 f(n, m),該函數的返回值爲最終留下的元素的序號。

首先,長度爲 n 的序列會先刪除第 m % n 個元素,然後剩下一個長度爲 n - 1 的序列。那麼,我們可以遞歸地求解 f(n - 1, m),就可以知道對於剩下的 n - 1 個元素,最終會留下第幾個元素,我們設答案爲 x = f(n - 1, m)。

由於我們刪除了第 m % n 個元素,將序列的長度變爲 n - 1。當我們知道了 f(n - 1, m) 對應的答案 x 之後,我們也就可以知道,長度爲 n 的序列最後一個刪除的元素,應當是從 m % n 開始數的第 x 個元素。因此有 f(n, m) = (m % n + x) % n = (m + x) % n。

 

fig1

我們遞歸計算 f(n, m), f(n - 1, m), f(n - 2, m), ... 直到遞歸的終點 f(1, m)。當序列長度爲 1 時,一定會留下唯一的那個元素,它的編號爲 0。

class Solution {
    int f(int n, int m) {
        if (n == 1)
            return 0;
        int x = f(n - 1, m);
        return (m + x) % n;
    }
public:
    int lastRemaining(int n, int m) {
        return f(n, m);
    }
};

其他方法:

文檔:約瑟夫環.note
鏈接:http://note.youdao.com/noteshare?id=ab67321edaaa3c68cf7ca9dd67fb9d02&sub=445688B547AC4F569E462F485698AD8D

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章