- 约瑟夫圆环
- python 实现版
list = list(range(1, 30 + 1))
print(list)
i = 0
index = 0
while list:
arr = list.pop(0)
index += 1
if index == 3:
index = 0
continue
list.append(arr)
print(list)
if len(list) == 2:
print(list)
break
i += 1
print(list)
list1 = [1, 23, 4, 5, 5, 6, 7, 1, 7, 8, 88, 9]
for i in list1:
list1.remove(i)
print(list1)
i = 0
while i < len(list1):
list1.remove(list1[i - 1])
list1.remove(list1[i ])
i += 1
print(list1)
-
Java实现版
List<Integer> list = new ArrayList<Integer>(); for (int i = 0; i < 30; i++) { list.add(i + 1); } int index = 0; while (true) { int a=list.get(0); list.remove(0); // 加入之前要判断这个人是否要死,要死不加 if (index == 2) { index = 0; continue; } list.add(a); if (list.size() == 2) { break; } index++; }
- Java泽哥版
package news.recommend.system.Util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class 约瑟夫3 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
// 数据准备
List<Integer> nums = new ArrayList<>();
for (int i = 1; i <= 30; i++) {
nums.add(i);
}
// 报数为3的删除
int removeNum = 3;
// 假设上一轮最后一个元素被删除,传递0
int previousLastNum = 0;
test(nums, removeNum, previousLastNum);
// 直接打印即可,因为传引入,不需要接收返回值
System.out.println(nums);
long endTime = System.currentTimeMillis();
System.out.println(endTime-startTime);
}
/**
*
- 1 先判断终止条(集合剩余个数 小于 要删除的数 就可以,就是removeNum)
- 2 获取当前次循环,最后一个数 喊得是几 currentLastNum
- 3 根据上一次循环最后一个数喊得数,获取本次递归要删除的元素
- 4 遍历nums 记录要删除的所有元素下标
- 5 倒叙遍历所有要删除的下标,对nums中元素进行删除
- 6 递归调用该方法,把新的nums 和 removeNum 以及 previousLastNum 传入
- @param nums
-
集合
- @param removeNum
-
要删除喊 m 元素
- @param previousLastNum
-
上一次循环中,最后一个元素喊的数,如果最后一个元素被删除,传入 0 即可
*/
public static void test(List nums, int removeNum, int previousLastNum) {
// 1 判断是否终止
if (nums.size() < removeNum) {
return;
}
// 当前轮最后一个元素喊 到几,
int currentLastNum;
// 如果上一轮(或者当前是第一轮) 最后一个元素喊 0 那么 当前最后一个元素喊的数 就是当前个数对m取余
if (previousLastNum == 0) {
currentLastNum = nums.size() % removeNum;
} else {
// 如果上一轮最后一个元素喊 2 , 那么 当前轮应该从 3 开始喊, 就等于当前的长度+上一轮最后一个喊的数字,对m取余
currentLastNum = (nums.size() + previousLastNum) % removeNum;
}
// n是上一轮最后一个元素喊到几, 如果是0 说明上一轮最后一个元素被删除,那么当前循环 还是删除 对m取余为0的
// 如果上一次最后一轮喊的2 , 那么当前次循环需要删除的数据就是 喊 (m-2)的
previousLastNum = previousLastNum == 0 ? 0 : removeNum - previousLastNum;
// 2 获取本轮需要被删除的元素的下标
List<Integer> indexs = new ArrayList<>();
// 遍历nums中元素 , 获取要被删除的元素的下标
for (int i = 1; i <= nums.size(); i++) {
if (i % removeNum == previousLastNum) {
indexs.add(i - 1);
}
}
// 倒着遍历所有下标,删除nums中元素
for (int i = indexs.size() - 1; i >= 0; i--) {
int index = indexs.get(i);
nums.remove(index);
}
test(nums, removeNum, currentLastNum);
}
}