博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
约瑟夫环
阅读量:5365 次
发布时间:2019-06-15

本文共 2639 字,大约阅读时间需要 8 分钟。

第18 题:

题目:n 个数字(0,1,…,n-1)形成一个圆圈,从数字0 开始,
每次从这个圆圈中删除第m 个数字(第一个为当前数字本身,第二个为当前数字的下一个数
字)。
当一个数字删除后,从被删除数字的下一个继续删除第m 个数字。
求出在这个圆圈中剩下的最后一个数字

 

约瑟夫环问题,第一思路是拿双向链表解决,从链表的头结点开始计数,数到第M个节点时,将该节点删除并从该节点的下一节点开始继续上述逻辑,直到开始节点的prev和next指针指向它自己,说明该节点是最后一个节点,但这种解决方法时间复杂度高,也没什么技术含量。。。。

另一个思路是用数学的方法,估计大家也都学过相应的解决方法,但我的感觉是理解的还是不彻底,可能跟数学逃课太多有关,汗

为了方便理解,我们假设下标从1开始,

初始序列1为 1,2,3,4,5,...,n-1,n   则第一个被删除的假设为K,则K=m%n (取余的目的是防止m大于n),K被删除后,剩下的n-1个值的序列2为

1,2,3,....k-1,k+1,...n-1,n

将1到k-1移至序列尾部 转换为序列3: k+1,k+2,k+3,....,n-2,n-1,n,1,2,3,...,k-1

将序列每个元素减去K,转换为序列4: 1,2,3......,n-2-k, n-1-k, n-k,.......,n-1    

  => 此处假设通过该序列我们能得到最终退出的元素是x,那么x与序列1最终退出的元素x'之间是不是相差K啊? 明白了么同志们?

又因为已知k=m%n

可以得到x'=x+k=x+m%n=(x+m)%n  因为x+m%n有可能大于n 所以转换为(x+m%n)%n也就是(x+m)%n

最终得到x'=(x+m)%n

1 package com.rui.microsoft; 2  3 public class Test18_Joseph { 4  5     public static void main(String[] args) { 6         int[] circle = {1,2,3,4,5,6,7,8,9,10}; 7         int m = 3; 8         int s = 0; 9         10         for(int i = 2; i <= circle.length; i++){11             s = (s + m) % i;12         }13         14         System.out.println(circle[s]);15     }16 }

 

另外双向链表的解法:

1 package com.rui.microsoft; 2  3 public class Test18_RemoveFromCircle { 4  5     public static void main(String[] args) { 6         Node node0 = new Node(0); 7         Node node1 = new Node(1); 8         Node node2 = new Node(2); 9         Node node3 = new Node(3);10         Node node4 = new Node(4);11         12         node0.next = node1;13         node1.pre = node0;14         node1.next = node2;15         node2.pre = node1;16         node2.next = node3;17         node3.pre = node2;18         node3.next = node4;19         node4.pre = node3;20         node4.next = node0;21         node0.pre = node4;22         23         Test18_RemoveFromCircle.remove(node0, 3);24     }25     26     public static void remove(Node head, int m){27         if(null == head) return;28         Node node = head;29         int start = 1;30         while(node != node.pre && node != node.next){31             while(start < m){32                 node = node.next;33                 start++;34             }35             node = remove(node);36             start = 1;37         }38         System.out.println(node.value);39     }40     41     private static Node remove(Node node){42         Node next = node.next;43         node.pre.next = next;44         next.pre = node.pre;45         return next;46     }47     48     static class Node{49         int value;50         Node pre;51         Node next;52         53         Node(int v){54             this.value = v;55         }56     }57 }

 

转载于:https://www.cnblogs.com/aalex/p/4907897.html

你可能感兴趣的文章
Android 编程下的代码混淆
查看>>
animation属性
查看>>
页内的模块和组件抽象规划经验
查看>>
安全-分析深圳电信的新型HTTP劫持方式
查看>>
将Centos的yum源更换为国内的阿里云源
查看>>
git diff 的用法
查看>>
一段sql的优化
查看>>
十进制与十六进制的相互转换
查看>>
在Flex中用Validator检测数字、字符串、Email.
查看>>
[leetcode]4Sum
查看>>
POJ1062 昂贵的聘礼
查看>>
【零基础学习iOS开发】【02-C语言】08-基本运算
查看>>
Java 将指定字符串连接到此字符串的结尾 concat()
查看>>
Hibernate Criterion
查看>>
Python知识
查看>>
我们为什么要搞长沙.NET技术社区(三)
查看>>
杭电acm Cake
查看>>
js函数中this的指向
查看>>
c++ 引用方式传递数组
查看>>
HBase学习之路 (九)HBase phoenix的使用
查看>>