第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 }