您的位置:首页 > 其它

链表之单链表约瑟夫问题(三)

2016-01-02 23:48 197 查看
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后[1]
结果+1即为原问题的解。

  约瑟夫环:递归算法

  假设下标从0开始,0,1,2 .. m-1共m个人,从1开始报数,报到k则此人从环出退出,问最后剩下的一个人的编号是多少?

  现在假设m=10

  0 1 2 3 4 5 6 7 8 9 k=3

  第一个人出列后的序列为:

  0 1 3 4 5 6 7 8 9

  即:

  3 4 5 6 7 8 9 0 1(*)

  我们把该式转化为:

  0 1 2 3 4 5 6 7 8 (**)

  则你会发现: ((**)+3)%10则转化为(*)式了

  也就是说,我们求出9个人中第9次出环的编号,最后进行上面的转换就能得到10个人第10次出环的编号了

  设f(m,k,i)为m个人的环,报数为k,第i个人出环的编号,则f(10,3,10)是我们要的结果

  当i=1时, f(m,k,i) = (m+k-1)%m

  当i!=1时, f(m,k,i)= ( f(m-1,k,i-1)+k )%m


  所以程序如下:

package com.zuo.linkedlist;

import java.util.MissingFormatArgumentException;

public class Josephuskill2 {
    static class Node{
        public int val;
        public Node next;
        public Node(int val){
        	this.val=val;
        }
    }
    public Node josephusKill(Node head,int m){
    	if(head==null || head.next==head || m<1){
    		return head;
    	}
    	int tmp=1;
    	Node cur=head;
    	while(cur.next!=head){  //得到链表的长度
    		tmp++;
    		cur=cur.next;
    	}
    	System.out.println("tmp"+tmp);
    	tmp=fun(tmp,m,tmp);  //计算出链表的下标 tmp=3;
    	System.out.println("final tmp"+tmp);
    	while(--tmp!=0){  //记住这个地方是!=0 ,一开始我写错了,把条件写成了--tmp==0
    		head=head.next;
    		System.out.println("value:"+head.val);
    	}
    	head.next=head;
    	return head;
    }
    public int fun(int m,int k,int i){
    	if(i==1){
    		return (m+k-1)%m;
    	}else{
    		System.out.println("m"+m+"k"+k+"i"+i);
    		return (fun(m-1,k,i-1)+k)%m;
    	}
    }
    public static void main(String[] args) {
		Node node0=new Node(0);
		Node node1=new Node(1);
		Node node2=new Node(2);
		Node node3=new Node(3);
		Node node4=new Node(4);
		Node node5=new Node(5);
		Node node6=new Node(6);
		Node node7=new Node(7);
		Node node8=new Node(8);
		Node node9=new Node(9);
		node0.next=node1;
		node1.next=node2;
		node2.next=node3;
		node3.next=node4;
		node4.next=node5;
		node5.next=node6;
		node6.next=node7;
		node7.next=node8;
		node8.next=node9;
		node9.next=node0;
		Josephuskill2 j=new Josephuskill2();
		Node head=j.josephusKill(node1, 3);
		System.out.println("+++++++++++++++++");
		System.out.println(head.val);
	}
}


结果:

tmp10
m10k3i10
m9k3i9
m8k3i8
m7k3i7
m6k3i6
m5k3i5
m4k3i4
m3k3i3
m2k3i2
final tmp3
value:2
value:3
+++++++++++++++++
3


总结:

我们先求出递归关系,然后得到下标,再求出链表中的第几个位置,这个时候时间复杂度降低了,为O(N)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: