约瑟夫算法的介绍:
约瑟夫环:已知n我的(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,
数到m的那我的出列;他的下一我的又从1开始报数,数到m的那我的又出列;依此规律重复下去,
直到圆桌周围的人所有出列java
如下为log信息,帮助理解实现思路算法
全部的数据为: 1 2 3 4 5 6 7 8 9 10 第1次循环,数据为: 1 2 3 4 5 6 7 8 9 10 -----------被删除的数据为:6 第2次循环,数据为: 7 8 9 10 1 2 3 4 5 -----------被删除的数据为:2 第3次循环,数据为: 3 4 5 7 8 9 10 1 -----------被删除的数据为:9 第4次循环,数据为: 10 1 3 4 5 7 8 -----------被删除的数据为:7 第5次循环,数据为: 8 10 1 3 4 5 -----------被删除的数据为:5 第6次循环,数据为: 8 10 1 3 4 -----------被删除的数据为:8 第7次循环,数据为: 10 1 3 4 -----------被删除的数据为:1 第8次循环,数据为: 3 4 10 -----------被删除的数据为:10 第9次循环,数据为: 3 4 -----------被删除的数据为:4 总数:[10] 须要删除掉的数据的位置:[6] 最后一个被删除掉的数据[3]
主要的实现思想:oop
2.一、两个list:一个装以前已经读过的数据,一个装尚未读过的数据code
2.二、从没有读过的数据里面删除应该删除的数据。rem
每次到应该删除的数据之后,将已经读过的数据放到没有读过的后面,以后再将已经读过的数据清空掉get
若是没有读过的数据,已经为空了,那么则须要将已经读过的数据再加进去,并将已经读过的数据清空class
2.三、判断,若是已经读过的数据list长度为1,未读数据为空,则结束循环test
/** * 约瑟夫算法的实现 * 约瑟夫算法的介绍: * 约瑟夫环:已知n我的(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数, * 数到m的那我的出列;他的下一我的又从1开始报数,数到m的那我的又出列;依此规律重复下去, * 直到圆桌周围的人所有出列 */ public class YuesefuTest { public static void main(String[] args) { int total = 5; int removeAt = 3; // patternTwo(total, removeAt); // patternTwo(10, removeAt); patternTwo(10, 6); // testOne(); } private static void testOne(){ ArrayList<Integer> unReadList = new ArrayList<Integer>();//没有读过的list ArrayList<Integer> readedList = new ArrayList<Integer>();//已经读过的list for(int i = 0;i< 5;i++){ unReadList.add(i); } for(int i = 5;i<10;i++){ readedList.add(i); } readedList.addAll(readedList.size(),unReadList); unReadList.clear(); System.out.println("全部的数据:"); for(int i = 0;i<readedList.size();i++){ System.out.println(" "+readedList.get(i)); } System.out.println(); System.out.println("剩下的数据:"); for(int i = 0;i<unReadList.size();i++){ System.out.println(" "+unReadList.get(i)); } } /** * 第二种方法 * @param total * @param removeAt */ private static void patternTwo(int total, int removeAt) { //两个list:一个装以前已经读过的数据,一个装尚未读过的数据 ArrayList<Integer> unReadList = new ArrayList<Integer>();//没有读过的list ArrayList<Integer> readedList = new ArrayList<Integer>();//已经读过的list for(int i = 1;i<=total;i++){ unReadList.add(i); } System.out.println("全部的数据为:"); printAllNum(unReadList); int loopCount = 1; while(true){ System.out.println("第"+loopCount+"次循环,数据为:"); printAllNum(unReadList); for(int i = 1;i< removeAt;i++){ if(unReadList.size() == 0){//若是没有读过的数据,已经为空了,那么则须要将已经读过的数据再加进去,并将已经读过的数据清空 unReadList.addAll(unReadList.size(),readedList); readedList.clear(); } int value = unReadList.remove(0); readedList.add(value); } if(unReadList.size() == 0){ unReadList.addAll(unReadList.size(),readedList); readedList.clear(); } int i = unReadList.remove(0);//从没有读过的数据里面删除应该删除的数据。 System.out.print(" -----------被删除的数据为:"+i+"\n"); //每次到应该删除的数据之后,将已经读过的数据放到没有读过的后面,以后再将已经读过的数据清空掉 unReadList.addAll(unReadList.size(),readedList); readedList.clear(); loopCount++; if(unReadList.size() == 1 && readedList.size() == 0){//判断,若是已经读过的数据list长度为1,未读数据为空,则结束循环 break; } } System.out.println("总数:["+total+"] 须要删除掉的数据的位置:["+removeAt+"] 最后一个被删除掉的数据["+unReadList.get(0)+"]"); } private static void printAllNum(ArrayList<Integer> allNum){ if(null != allNum && allNum.size() > 0) { System.out.println(); for (int i =0;i<allNum.size();i++) { System.out.print(" "+allNum.get(i)); } System.out.println(); } } }