约瑟夫算法总结

  • 约瑟夫圆环

  • 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);

}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值