链表之单链表约瑟夫问题(三)
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
结果+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)相关文章推荐
- TmFunctions
- 解决undefine reference to '__aeabi_idiv' undefine reference to '__aeabi_idivmod'错误
- 【转】Eclipse上安装GIT插件EGit及使用
- voice lab2 – GK Operations
- TmDateUtil
- 《笨办法学Python》 第3课手记
- EasyUI1.4.4 + zTree3.5.19 完美结合框架布局 tree+tab
- 动画封装四:用json实现多条样式的缓动运动
- StringUtils
- 解题报告:HDU_1709 The Balance
- Fast Pixel Operations in .NET (With and Without unsafe)
- Java 创建多线程
- 初识HTML(5)——图形
- struts配置
- (maven)继承
- 合数幂上下分解表
- Shell编程进阶 2.1 shell函数
- 判断一个字符串是否为另外一个字符串旋转之后的字符串
- 手势解锁的实现
- 15年的最后总算是熬过去了,16年先放松两天