数据范围: 1≤n,m≤10000
import java.util.*;
public class Solution {
class node//创建链表节点
{
int val;
node(int val) {
this.val=val;
}
node next;
}
public int ysf(int n, int m) {
if(m==1)return n-1;//一次一个直接返回最后一个即可
node pHead = new node(1);
node pTail = pHead;//创建一个链表
for(int i=2;i<=n;i++)
{
pTail.next=new node(i);
pTail=pTail.next;
}
pTail.next=pHead;//使形成环
int count = 1;//从1开始计数
while (pHead.next!=pHead) {//当剩余节点不止一个的时候
//如果count=m-1 那就说明下个节点该删除了
if(count == m-1)
{
pHead.next = pHead.next.next;
count = 1;
}
else {
count++;
}
pHead = pHead.next;
}
return pHead.val;
}
}
import java.util.*;
class Solution {
public int ysf(int n, int m) {
if(m==1) return n-1;
List<Integer> list=new ArrayList<>();
for(int i=0;i<n;i++)
{
list.add(i);
}
int index=0;
while (list.size()>1)
{
index=(index+m-1)%(list.size());
list.remove(index);
}
return list.get(0)+1;
}
}
public class Solution {
public static int ysf(int n, int m) {
if (m == 1) return n - 1;
boolean[] arr = new boolean[n];
int count = 0;//排除的次数
int k = 1;//k等于m时排除那个数
int i = 0;//当前元素下标
while (count != n) {
i++;
if (i == n) {
i = 0;
}
if (arr[i] == false) {
k++;
if (k == m) {
arr[i] = true;
count++;
k = 0;
}
}
}
return i + 1;
}
}
编号一定从0开始(取模有0 ,可以形成循环)
题目中编号是从1开始,之后可以变为从0开始,然后+1返回
所以已知下一行答案列的值,可以加上偏移量再%当前行的n得出这一行答案列的值
{ y s f ( n , m ) = 0 , n = = 1 y s f ( n , m ) = ( y s f ( n − 1 , m ) + m ) % n , n ! = 1 \left\{ \begin{matrix} ysf(n,m)=0,n==1 \\ ysf(n,m)= (ysf(n-1,m)+m) \% n, n!=1 \end{matrix} \right. {ysf(n,m)=0,n==1ysf(n,m)=(ysf(n−1,m)+m)%n,n!=1
只能获得最后存活者的编号,无法像模拟法一样可以获取淘汰过程中的编号序列。
按照牛客网题目要求编号从1开始
class Solution {
public int ysf(int n, int m) {
if(n==1)
return 1;
return (ysf(n-1,m)-1+m)%n+1;//先-1下标从0开始计算,之后+1变成从1开始
}
}
多一个参数i,表示淘汰的次数,这样可以获取淘汰过程中的编号序列
int ysf(int n,int m,int i) {
if(i==1) {
return (m-1)%n;
}
return (ysf(n-1,m,i-1)+m)%n;
}
反推过程:(当前index + m) %当前人数。
import java.util.*;
public class Solution {
public int ysf (int n, int m) {
//答案列最后的值
int index = 0;
//从倒数第二行开始
for (int i = 2; i <= n; i++) {
index = (index + m) % i;
}
return index+1;
}
}