洛谷 P1996 约瑟夫问题(链表或数组模拟)

题目链接: 以下提供两种思路,一种是纯模拟(题目数据小,只有100),一种是链表(貌似还是模拟哈哈) 1.上代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int main(){
    int n,m;
    int a[105]={
         
  0};//标记这个人是否被踢出去
    scanf("%d %d",&n,&m);
    if(m==0)m=n;//如果m等于0,把m置为n
    int num=n;//目前还剩下的人
    int last=1;//上一次的最后一人
    while(num){
         
  //只要还有人
        int cnt=0;//一个累加变量
        for(int i=last;cnt!=m;i++){
         
  //从最后一人开始,数到m为止
            if(i>n)i%=n;//在下面的程序中出现了加到比n大的情况,就模n
            if(a[i]==-1)continue;//被踢出去了就continue
            ++cnt;//cnt+1
            if(cnt==m){
         
  //数到m了
                a[i]=-1;//把这个人踢出去
                num--;//还在的人数-1
                last=i+1;//下一次数的起点
                printf("%d ",i);//输出
                break;
            }
        }
    }
return 0;
}

2.链表

//循环链表实现。流程:数到这个人就把这个人从链表元素中删除并输出编号
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
struct node{
    int data;
    node *next;
};
int n,m;
node *head,*p,*r;
int main(){
    scanf("%d %d",&n,&m);
    if(m==0)m=n;//同上
    head=new node;//申请空间
    head->data=1;//头节点数据置为1
    head->next=NULL;//头节点下一个为空
    r=head;//尾指针现在是头
    for(int i=2;i<=n;i++){
        p=new node;
        p->data=i;
        p->next=NULL;
        r->next=p;//把申请的新节点连到前面的链表上
        r=p;//尾指针后移一个
    }
    r->next=head;//尾指针指向头
    r=head;//循环链表建立完成
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m-2;j++)r=r->next;//循环到m的前两个人
        cout<<r->next->data<<" ";//输出这第m个人的数据
        r->next=r->next->next;//跳过这个节点
        r=r->next;//新的一轮从上次的最后一个的下一个开始
    }
return 0;
}

总结:用来练习数据结构的基础题·

经验分享 程序员 微信小程序 职场和发展