循环数组pos=(pos+1 )%n 如果pos代表数组下标,数组一定要利用下标0

7-8 数组循环左移 (20 分)

本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置(最前面的m个数循环移至最后面的m个位置)。如果还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?

输入格式:
输入第1行给出正整数n(≤100)和整数m(≥0);第2行给出n个整数,其间以空格分隔。

输出格式:
在一行中输出循环左移m位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
8 3
1 2 3 4 5 6 7 8
输出样例:
4 5 6 7 8 1 2 3

循环数组写法

#include <bits/stdc++.h>
using namespace std;
int a[105];
int n,m;
void move3(){ 
	for(int i=0;i<m;i++){
		for(int j=1;j<=n;j++){
			a[j-1]=a[j];
		}
		a[n]=a[0];
	}
	for(int i=1;i<=n;i++){
		if(i!=n)cout<<a[i]<<" ";
		else cout<<a[i];
	}
}
void reverse(int l,int r){//将数组l~r段转置  12345
	 int s=(r-l+1)/2;//转置次数 
	 int temp; 
	 for(int i=0;i<s;i++){//while(r>l)
	 	temp=a[l];
	 	a[l]=a[r];
	 	a[r]=temp;
	 	l++;
	 	r--;
	 }
}
void move2(){
	reverse(1,m);
	reverse(m+1,n);
	reverse(1,n);
	for(int i=1;i<=n;i++){
		if(i!=n)cout<<a[i]<<" ";
		else cout<<a[i];
	}
}
void move1(){// 1 2 3 4 5 6  左移动2个位置
//	int j=n-m;//右移动 
//	j%=n;//之前已经m%=n,n-m<=n  m=0时n-m要为0 
	int j=m+1;//左移 
	for(int i=0;i<n;i++){
		if(i!=n-1)cout<<a[j]<<" ";
		else cout<<a[i];
		j=(j+1)%n;//循环数组的写法 
	} 
	
} 
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
//1、不移动,靠输出
//2、转置1~m,m+1~n,1~n//移动次数最少
//3、普通移动,一个一个地移动 
	cin>>n>>m;
	m=m%n;//如果m大于n,移动n次之后与移动0次没区别 
	for(int i=1;i<=n;i++){
		cin>>a[i];
	} 
	move1();
//	move2();
//	move3();
    return 0;
} 

约瑟夫问题

http://noi.openjudge.cn/ch0302/solution/32938506/

#include <bits/stdc++.h>
using namespace std;
int vis[302];//出列的记为1 
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n,m;//n只猴子,叫到m号的出列
	while(cin>>n>>m){
		if(n==0&&m==0)break;
		memset(vis,0,sizeof(vis));
		int cnt=0;//记录出列的猴子,n-1只 
		int sign=1;//叫号 
		int num=0;
//真正的序号 vis[0]必须从下标0开始(不能是1 因为对n求余用到的是0~n-1 
		while(true){
			if(!vis[num]){
				if(sign!=m)sign++;//下一只猴子叫号 
				else{
					sign=1;//下次从1叫号 
					cnt++;//出列
					vis[num]=1; 
				} 
			}
		num=(num+1)%n;//循环的遍历这些猴子 出列的猴子相当于直接跳过 
		if(cnt==(n-1)&&!vis[num]) {
			cout<<num+1<<endl;
			break;
		}
	} 
	}
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值