1. 程式人生 > 其它 >【劍指offer中等部分18】孩子們的遊戲(java)

【劍指offer中等部分18】孩子們的遊戲(java)

技術標籤:劍指offerjava演算法資料結構

一、題目描述

每年六一兒童節,牛客都會準備一些小禮物去看望孤兒院的小朋友,今年亦是如此。HF作為牛客的資深元老,自然也準備了一些小遊戲。其中,有個遊戲是這樣的:首先,讓小朋友們圍成一個大圈。然後,他隨機指定一個數m,讓編號為0的小朋友開始報數。每次喊到m-1的那個小朋友要出列唱首歌,然後可以在禮品箱中任意的挑選禮物,並且不再回到圈中,從他的下一個小朋友開始,繼續0…m-1報數…這樣下去…直到剩下最後一個小朋友,可以不用表演,並且拿到牛客名貴的“名偵探柯南”典藏版(名額有限哦!!)。請你試著想下,哪個小朋友會得到這份禮品呢?(注:小朋友的編號是從0到n-1)

二、分析

2.1 連結串列

這其實就是一個約瑟夫環問題,往後走m次,然後彈出一個數,重複上述過程,直到全部彈出。回到該題,先將每個小朋友編號新增進去,之後走m次,重複過程,直到只剩一個,即為最終勝利者。這個方法也是最好理解,最容易想到的,一個團體就可以想到用集合方式,這道題就很符合集合add、remove操作。

import java.util.LinkedList;
public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if(n <= 0 || m <= 0){
            return
-1; } LinkedList<Integer> list = new LinkedList<Integer>(); for(int i = 0 ; i < n ; i++){ list.add(i); } int index = 0; while(list.size() > 1){ index = (index + m -1) % list.size(); //剩餘隊伍繼續遊戲 list.remove
(index); } return list.get(0); //最後只剩一個,返回 } }

在這裡插入圖片描述

2.2 遞迴

用遞迴就要明白,這個題的底層邏輯,它就是首先從0開始報數,報到m-1出列,剩下n-1個人。然後從m開始報數,m報0,m+1報1,這樣要報m次,故得f(n, m) = f(n-1,m)+m,加m是因為已經報了一輪。注意要對式子%n,以至於實現迴圈。

實現程式碼如下 :

import java.util.LinkedList;
public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if(n==0) return -1;
        if(n==1) return 0;
        return (LastRemaining_Solution(n-1,m) + m)% n;
    }
}

在這裡插入圖片描述