1. 程式人生 > >劍指offer——(12)約瑟夫出圈

劍指offer——(12)約瑟夫出圈

關於約瑟夫出圈是有一個故事的,去年資料結構課老班有講過,記不清了,有興趣的可以自己去搜下。想起來當年剛學連結串列老師佈置了這麼一道類似的題,我還覺得很難,難到我根本寫不出來,,絞盡腦汁又看了題解才交了作業,現在回過頭去看,其實是很簡單的一道演算法題。

我這裡加了個連結串列版,算是擴充,可以決定第一次的時候從第幾個開始計數,思路全寫在註釋裡了,表達能力欠佳,應該能看懂吧哈哈哈。

public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if(n==0||m==0) return -1;
        int circle[] = new int[n];
        for(int i=0;i<n;i++) circle[i] = i;
		int i=0,j = 0;
		while (n > 0) {
			j = (i + m - 1) % n;	
			i = j;		
			for (; j < n - 1; j++) {
				circle[j] = circle[j + 1];
			}
			n--;			
			}
		return circle[j];	      
    }
}
import java.util.Scanner;
public class Solution {
	Node head=new Node(); //頭結點 指標 不儲存data
	Node t=head;
	public Solution() {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt(); //圍成圈的人數
		int k=sc.nextInt(); //從第幾位開始計數 這裡規定可以從0開始
		int m=sc.nextInt(); //決定從1數到m出局
		//從0開始 連結串列儲存
		for(int i=0;i<n;i++){
			t = t.next=new Node(i);
		}
		//t指向最後一個節點 最後一個節點指回頭節點的next 形成環連結串列
		t.next=head.next;
		//指向第k位 準備從這裡從1開始計數
		for(int i=1;i<=k;i++) t=t.next;
		//temp指向t.next即未成環時第一位
		Node temp=t.next;
		//q指向出圈結點的前驅結點
		Node q=null;
		//出圈開始 全部人出圈就結束
		while(n>=1){
			//從第k位開始數 數k-1次 此時temp指向的節點出圈
			for(int i=1;i<m;i++){
				q=temp;			
				//System.out.print(q.data+" ");
				temp=temp.next;
				//System.out.println(temp.data);
		}
			//第m個人出圈
			System.out.println(temp.data);	
			//用前驅結點q刪除出圈結點
			q.next=temp.next;
			//同時繼續出圈遊戲的temp環連結串列也要指向下一個節點
			temp = temp.next;
			//遊戲人數不斷減少
			n--;
		}
	}

	public static void main(String args[]){
		new Solution();		
	}
}
	class Node{
		public int data;
		public Node next;
		public Node(){ }
		public Node(int data){
			this.data=data;
			this.next=null;
		}
}