1. 程式人生 > >LastRemaining45(圓圈中最後剩下的數字(約瑟夫問題))

LastRemaining45(圓圈中最後剩下的數字(約瑟夫問題))

import java.util.LinkedList;

/**
 * @author LemonLin
 * @Description :LastRemaining45
 * @date 2018/9/4-20:45
 *
 * 題目:圓圈中最後剩下的數字(約瑟夫問題)
 *
 * 題目:0, 1, … , n-1 這 n 個數字排成一個圈圈,
 * 從數字 0 開始每次從圓圏裡刪除第 m 個數字,下一次,從m+1開始數,數第
 * m個刪除,以此類推。求出這個圈圈裡剩下的最後一個數字。
 *
 * 問題,需要解決如何迴圈移除的問題?用%(list.size())
 *
 *需要解決如何進行下一步繼續迴圈的問題,比如第一遍數到0-M,如何第二遍從m+1開始數第m個數:
 *
 * index=-1;
 * while(size>1){
 *     index=(index+m)%size();
 *     index--;
 * }
 * 原因,第一次取m-1,
 * 第二次是index--是因為size也減小了一個一;
 * 迴圈是用%size();
 *
 *
 * 解題思路:
 * 解法一:利用環形連結串列處理問題,這裡用LinkedList的效能比ArrayList的效能好,
 * 因為我們不斷的要刪除List中的某個元素。如果用ArrayList裡面有大量的System.arraycopy。
 *
 *
 * 解法二:開O(n)的輔助空間,建造一個boolean陣列,大小為總共數字的個數和,預設boolean
 * 陣列的每個元素都是false,數到誰的時候,將陣列對對應index的值改為true。
 * 知道最後只剩下一個元素值為false,得到此index。
 */
public class LastRemaining45 { /** * * @param n 表示圓圈最大的數 * @param m 表示從第幾個數開始刪除 * @return 剩下的最後一個數 */ public int LastRemaining_Solution(int n, int m) { /** * 異常輸入的判斷 */ if (n==0||m==0){ return -1; } LinkedList<Integer> linkedList = new
LinkedList<>(); for (int i=0;i<n;i++){ linkedList.add(i); } /* for(Iterator iter = linkedList.iterator(); iter.hasNext();) { System.out.println("原始linkedList==="+iter.next());; }*/ int index =-1; while (linkedList.size()>1
){ index=(index+m)%(linkedList.size()); linkedList.remove(index); /*System.out.println("移除過程中的linkedList==="+m);*/ index--; } /* for(Iterator iter = linkedList.iterator(); iter.hasNext();) { System.out.println("移除之後linkedList==="+iter.next()); }*/ return linkedList.get(0); } public static void main(String[] args) { LastRemaining45 lastRemaining45 = new LastRemaining45(); int test = lastRemaining45.LastRemaining_Solution(5, 3); System.out.println(test); } }