一行两个整数 n,m,n 表示链表的长度,m 表示每报数到 m 就自杀。
输出最后存活的人的编号(编号从 1 开始到 n)。
5 2
3
import java.util.Scanner;
// 一行两个整数 n,m,n 表示链表的长度,m 表示每报数到 m 就***。
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
Person killed = null; // ***的人
Person aheadKilled = null; // ***之前的人,因为是单项环形链,要想形成链就得知道最后一个人,也就是***的人之前的那个人
Person newPerson; // 临时变量,新Person,放在循环之外
// 先组成一个链表
// 创建N个结点,形成单项环形链
for (int i = 1; i <= n; i ++) {
newPerson = new Person(i);
// 如果是第一个人,那么自己和自己形成环形链
if (killed == null) {
killed = newPerson; // 默认***的就是第一个人
aheadKilled = newPerson; // ***之前的那一个人也是自己,因为就剩一个人了
killed.next = newPerson; // 自己的下一个人指向自己
} else { // 如果不是第一个人,则在末尾处添加新的人
aheadKilled.next = newPerson; // 原***之前的那一个人的后一个人指向新Person
aheadKilled = newPerson; // 新的***之前的那一个人指向新的Person
newPerson.next = killed; // 新Person的后一个人指向***的人
}
}
// 如果环内所剩之人一直大于1人,那么一直查数
// killed与aheadKilled指针相同时,证明环内只剩一人
while (killed != aheadKilled) {
// 每报数到m就***,从1开始数,killed实际上移动了m-1次,例如每报数3就***,那么killed指针移动了3-1次,即1->2,2->3共2次
// 相对应的,***之前的一个人也移动m-1次
for (int i = 0; i < m - 1; i ++) {
killed = killed.next;
aheadKilled = aheadKilled.next;
}
// 移动完毕之后,此时killed指针指向的Person即为***之人,将此人从环中除去,即killed后移一位
killed = killed.next;
// 重新形成环
aheadKilled.next = killed;
}
// 此时最后剩下的killed或aheadKilled指向的Person即为最后剩余之人
System.out.print(killed.number);
}
}
class Person {
public Person(int number) {
this.number = number;
}
int number; // 编号
Person next; // 下一个人
}