算法學習之圓圈中最後剩下的數字

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

解法一:使用LinkedList仿圓就可以了,很簡單

import java.util.*;
public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if(n<=0||m<=0)return -1;
        LinkedList<Integer> list = new LinkedList();
        for(int i =0;i<n;i++){
            list.add(i);
        }
        int cur = 0;
        while(list.size()>1){
            cur = (cur+m-1)%list.size();
            list.remove(cur);
        }
        return list.getFirst();
    }
}

時間複雜度:O(n)

空間複雜度:O(n)

解法二:使用數學公式遞推

1、首先定義剩下的數:f(n,m)

2、第一個被刪除的數字爲s,由解法一我們可以知道s=(m-1)%n

3、當刪完s以後,剩下的數字爲0,1...,s-1,s+1,...n-2當從k+1處繼續開始數m個數,我們以k+1爲開頭

當前數組排列爲:s+1,s+2,  ... 0,     1,       ...s-1

對應映射數組爲:0    ,1    ,  ... n-2-s,n-1-s...,n-2

這裏設映射數字爲x,當前數字爲y。y=(x+s+1)%n

在映射的數組中,因爲我們定義的n個數最後一個數字爲f(n,m),所以在刪除了s之後n-1個數字最後一個數爲f(n-1,m)

把f(n-1,m)轉換成當前數組中的數字即帶入上方公式得:(f(n-1,m)+s+1)%n

4、最終我們有第一步定義的f(n,m) = (f(n-1,m)+s+1)%n,簡化爲:(取餘部分可直接提出,因爲一次跟兩次效果是一樣的)

f(n,m) = (f(n-1,m)+m)%n

當n=1時:f(1,m) = 0

推的是不是很煩!!!看看代碼就高興了,因爲很少,哈哈

import java.util.*;
public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if(n<=0||m<=0)return -1;
        
        // 因爲f(1,m) = 0;所以last取0,n從2開始
        // 並且f(n,m) = (f(n-1,m)+m)%n所以循環條件i可以=n
        int last = 0;
        
        for(int i =2;i<=n;i++){
            last = (last+m)%i;
        } 
        return last;
    }
}

時間複雜度:O(n)

空間複雜度:O(1)

練習地址:https://www.nowcoder.com/practice/f78a359491e64a50bce2d89cff857eb6

發佈了94 篇原創文章 · 獲贊 8 · 訪問量 5134
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章