编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。
下一个人继续从 1 开始报数。
n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?
数据范围:
进阶:空间复杂度
,时间复杂度
5,2
3
开始5个人 1,2,3,4,5 ,从1开始报数,1->1,2->2编号为2的人离开 1,3,4,5,从3开始报数,3->1,4->2编号为4的人离开 1,3,5,从5开始报数,5->1,1->2编号为1的人离开 3,5,从3开始报数,3->1,5->2编号为5的人离开 最后留下人的编号是3
1,1
1
import java.util.*;
public class Solution {
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
public int ysf (int n, int m) {
// write code here
return f(n, m) + 1;
}
private int f (int n, int m) {
if (n == 1) {
return 0;
}
return (f (n - 1, m) + m) % n;
}
}
import java.util.*;
public class Solution {
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
public int ysf (int n, int m) {
// write code here
ArrayList<Integer> ysf = new ArrayList<>(); // list集合模拟约瑟夫环
for (int i = 1; i <= n; i++) {
ysf.add(i); // 装载人
}
int index = 0;
while (ysf.size() != 1) {
index = (index + m - 1) % ysf.size(); // 报数 直到指定的数
ysf.remove(index); // 人出列
// index = (index + 1) % ysf.size(); // 从出列的下一个人开始数数
// 因为人出列了,所以这个index这个位置被出列后一个人占了,不需要进行处理了
}
return ysf.get(0);
}
} /*
解设: f(n,m) 表示 n 个编号,报号到 m 的最终那个编号
则: 为了方便取模,编号序列从 0 开始 即
1 2 3 4 5 6 ... ,k-1, k, k+1, k+2 ... n
初始序列状态:
0 1 2 3 4 5 ... ,k-2, k-1 k, k+1 ... n-1
即 seq1 = [0,1,2...n-1]
递推:
那么 f(n,m) 与 f(n-1,m)有啥关系呢?
1. 假设第一轮取第 m 个数取到编号为 k 的序列, 即 k = (m-1) % n
2. 则取完后,f(n-1, m)的起点状态变化为:
0 1 2 3 4 5 ... , k-2, k-1, k, k+1 ...,n-2
k+1 k+2 k+3 k+4 k+5 k+6 ... , n-1, 0 , 1, 2 ...,k-1
设 seq2 = [k+1, k+2,..., 0, 1, 2, ..., k-1]
则 从seq1 映射到 seq2 函数为: g(x) = (x+k+1) % n //根据地址里的序列变换到另一个序列
f(n,m,seq1) 表示 n 个元素,取第 m 个位置的,以seq1序列为内容的值,f对最终选取的位置与seq无关
= f(n-1, m, seq2)
= f(n-1, m, g(seq1))
= g(f(n-1, m, seq1))
//不管是序列seq1还是序列seq2,选择的第 m 个位置(地址)一定是相同的,所以可以先选位置,再交换空间内容
即
f(n,m) = g( f(n-1, m) )
= (f(n-1,m) + k + 1) % n when k = (m-1) % n
f(1,m) = 0 // 1 个元素,选第 m 个元素一定是 0 (默认seq1顺序,不带seq形参)
*/
class Solution {
public:
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*///for循环搞定
int ysf(int n, int m) {
int ans = 0, k;
for(int i = 1; i<n; ++i){
k = (m-1)%(i+1);
ans = (ans + k + 1)%(i+1);
}
return ans+1;
}
}; import java.util.*;
public class Solution {
public int ysf (int n, int m) {
// write code here
LinkedList<Integer> list = new LinkedList<>();
for (int i=1;i<=n;++i){
list.addLast(i);
}
int curr = 0;
while (list.size() > 1){
int size = list.size();
int pos = (curr+m-1)%size;
list.remove(pos);
// // 当只剩下最后一个时候,令cur==0
// if(size-1==1)
// curr=0;
// else //其实注释掉的这部分没有也可以,因为及时最后size为0了,curr为1,可是便立即结束了循环,不会边界溢出的
curr=pos;
}
return list.get(0);
}
} import java.util.*;
public class Solution {
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
public int ysf (int n, int m) {
// write code here
ArrayList<Integer> ysf = new ArrayList<>();
for(int i = 1; i <= n; i++){
ysf.add(i);
}
int curr = 0;//当前位置
while(ysf.size() > 1){
int size = ysf.size();
int removePos = (curr + m - 1) % size;//当前要被删除的节点的位置
ysf.remove(removePos);
curr = removePos % (size - 1); //当前起点的位置。如果删除的是最后一个重置curr为0。
}
return ysf.get(0);
}
}
// 1 2 3 4 5 -> 1 3 4 5 -> 1 3 5 -> 3 5 -> 3 class Solution {
public:
ListNode* createList(int n) {
ListNode *head = new ListNode(1);
ListNode *p = head;
for(int i = 2; i <= n; i++) {
ListNode *node = new ListNode(i);
p->next = node;
p = node;
}
p->next = head;
return head;
}
int ysf(int n, int m) {
ListNode *head = createList(n);
ListNode *p = head, *pre = NULL;
while(p->next != p) {
for(int i = 1; i < m; i++) {
pre = p;
p = p->next;
}
// 删除结点p
pre->next = p->next;
delete p;
p = pre->next;
}
return p->val;
}
}; import java.util.*;
public class Solution {
public int ysf (int n, int m) {
// write code here
LinkedList<Integer> list = new LinkedList<>();
for (int i=1;i<=n;++i){
list.addLast(i);
}
int curr = 0;
while (list.size() > 1){
int size = list.size();
int pos = (curr+m-1)%size;
list.remove(pos);
curr = pos % (size-1); // 若删除的是最后一个,重置curr为0
}
return list.get(0);
}
} import java.util.*;
public class Solution {
static class Ring{
// 单向环形链表
class RingNode{
int val;
RingNode next;
public RingNode(int val){
this.val = val;
this.next = null;
}
}
public RingNode head = null;
public RingNode tail = null;
public RingNode cur = null;
// 添加元素
public void add(int val){
if(head == null){
head = new RingNode(val);
head.next = head;
cur = head;
tail = head;
}else{
// 新添加的元素放在循环链表的末尾
tail = new RingNode(val);
tail.next = head;
cur.next = tail;
cur.next.next = head;
cur = cur.next;
}
}
// 删除元素
public boolean delete(int m){
// 循环链表中只剩余一个元素
if(head.next == head){
return false;
}
// 确定待删除的元素
RingNode todel = cur;
for(int i = 1; i < m; i++){
cur = todel;// cur移动到待删除的元素的前一个位置
todel = todel.next;
}
// 待删除的元素为从当前节点开始的第二个指针
if(head == todel){
// 待删除的节点是头指针
head = head.next;
tail.next = head;
cur = head;
}else if(tail == todel){
// 待删除的节点是尾指针
RingNode p = head;
while(p.next != tail){
p = p.next;
}
tail = p;
tail.next = head;
cur = head;
}else{
// 待删除的节点不是头尾指针
cur.next = todel.next;
cur = todel.next;
}
return true;
}
}
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
public int ysf (int n, int m) {
Ring ring = new Ring();
// 添加元素到队列中
for(int i = 0; i < n; i++){
ring.add(i + 1);
}
// 将当前节点重新定位到头结点
ring.cur = ring.head;
// 循环删除
while(ring.delete(m));
return ring.head.val;
}
} import java.util.*;
public class Solution {
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
public int ysf (int n, int m) {
// write code here
//先用列表记录各个数的下标位置
if(n==1) return 1;
List<Integer> list = new ArrayList();
for(int i = 1;i<=n;i++){
list.add(i);
}
//当前指针正指向的位置
int cur = 0;
while(list.size()>1){
//当前遍历时还剩多少人
int size = list.size();
//当前列表要删除元素的下标
cur = (cur+m-1)%size;
//删除指定下标元素
list.remove(cur);
}
//返回最后剩下人的下标
return list.get(0);
}
} class Solution: def ysf(self , n , m ): # write code here res = [i + 1 for i in range(n)] i = 0 for j in range(n-1): i = (i + m - 1) % (n - j) del res[i] return res[0] # 取一个数组,循环删除
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
int ysf(int n, int m ) {
// write code here
struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
struct ListNode *p = head;
head->val = 1;
for (int i = 2; i <= n; i++) {
struct ListNode *node = (struct ListNode *)malloc(sizeof(struct ListNode));
p->next = node;
p = node;
p->val = i;
}
p->next = head;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m - 1; j++) {
head = head->next;
}
struct ListNode *q = head->next;
head->next = q->next;
free(q);
head = head->next;
}
return head->val;
} struct Node {
int val;
Node* next;
Node() : val(0), next(nullptr) {}
Node(int _val) : val(_val), next(nullptr) {}
Node(int _val, Node* _next) : val(_val), next(_next) {}
};
class Solution {
public:
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
int ysf(int n, int m) {
Node* head = new Node(1), *tail = head; // 头尾指针
for (int i = 2; i <= n; ++i) {
Node* node = new Node(i);
tail = tail->next = node; // 尾插手法
}
tail = tail->next = head; // 形成环
for (int i = 0; i < n - 1; ++i) {
for (int j = 1; j < m - 1; ++j)
tail = tail->next;
Node* node_to_delete = tail->next;
tail = tail->next = tail->next->next;
delete node_to_delete;
}
return tail->val;
}
};