约瑟夫环问题

约瑟夫环问题,假设有10个人围成一圈,从1,开始报数,数到3的人退出,下一个人继续从1开始数,问,最后剩余的是哪一个人?

思路,1.剩余的人是第几个,返回值是整型,将这10个人放到一个数组中,数到3的人退出,直到最后只剩下一个人,数组要循环遍历。2.参数设定,用left 变量来表示剩余人数,count变量表示报数器,num表示指定退出的数,while(left > 1),剩余人数大于1,就一直进入循环,再循环内部,先判断这个人报的数是不是3,如果不是,count++;,同时,i++,数组向后遍历。如果这个人报的数是3,那么count得变成0,同时剩余人数left得--,i++;3.第一遍数组完全遍历后,也就是第十个人报数1的时候,怎么再次循环遍历剩余的数据?在循环里面进行条件判断时,我们会发现,不管报的数是不是指定退出的数3,i 都得自增,让数组向后遍历,每次i自增后,都让i对10取余,这样无论i自增到多少,对10取余后,都是个位数,从而实现数组的循环遍历。这里对第二个条件进行补充,怎么判断这个人报的数是不是三,我如果第i 个人报数为3,就让arr[i] = -1;这样条件判断时,if(arr[i] !=-1){count++;},count 是计数器,如果他等于3 ,那么就把-1赋值给arr[i]; if(count=num){arr[i] = -1;……},同时也不影响第三步循环遍历数组。

最后一步,返回值是数组中的某一个数arr[i];

for(int i = 0; i < len; i++){

if(arr[i] != -1){  return arr[i];}

所以封装的函数为一个返回值为整型,形式参数为数组名,数组长度,指定退出的数num

代码如下

int ysf_cycle(int* arr, int len, int num) {
	int left = 10;//剩余人数
	int i = 0,count = 0;
	while (left > 1) {
		if (arr[i] != -1) {
			count++;
		}
		if (count == num) {
			arr[i] = -1;
			count = 0;
			left--;
		}
		i++;
		i = i % len;
	}
	for (int i = 0; i < len; i++) {
		if (arr[i] != -1) {
			return arr[i];
		}
	}
	//return -1;

}
int main() {
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int len = sizeof(arr) / sizeof(arr[0]);
	printf("%d \n", ysf_cycle(arr, len, 3));
	return 0;

2.最简单的字符串转整型就是把字符串常量“123”,转变成十进制的123。

思路:先用遍历这个字符串数组,得到每一个字符。2.要获取字符串中字符的个数bit,3.用数学公式,1*10^(bit - 1) + 2*10(bit-2)+3*10(bit - 3) . 怎么获取字符串中字符的个数,在头文件<ctype.h>中,有一个isdight函数,用于判断这个字符是不是数字字符,用法如下,字符串的结尾标记'\0',

int getbit(const char* arr) {
	int count = 0;
	while (*arr != '\0') {
		if (isdigit(*arr)) {
			count++;
		}
		arr++;
	}
	return count;
}

  3.获取位数后,用数学公式计算

int my_atoi(const char*arr) {
	int result = 0;
	int bit = getbit("123");
	while (*arr != '\0') {
		result+=(*arr - '0')* pow(10, bit - 1);
		bit--;
		arr++;
	}
	return result;
}
int main() {
	
	 printf("%d\n", my_atoi("123"));
	 return 0;
}

3.一个数组中有n个数据,怎么样把后面m 个数据移到前边,前面n - m 个数据移到后面,比如

123456,给它换成56,1234。思路:第一步,用一个逆转函数,将123456变为654321,第二步,将6和5用逆转函数转变成56,第三步,用逆转函数将4321转变成1234。

 具体实现: 逆转函数,在数组123456中,将1和6交换,2和5交换,3和4交换。6个数交换3次,所以,数组长度len可以控制循环次数,用len/2来控制。第二个问题,数组1到6交换后,654321,第二次交换6和5的左右下标,所以,逆转函数中要有的参数有左右下标,还有数组名

代码如下

void reverse(int* arr, int left,int right,int len) {
	for (int i =0;  i<len / 2; i++) {
		int temp = arr[i+left];//i+加left可以保证第三次交换的左下标从2号下标开始,
		arr[i+left] = arr[right-i];
		arr[right-i] = temp;
	}
}
void adjust_array(int*arr,int len,int m) {
	
	reverse(arr, 0, len-1,len);
	reverse(arr, 0, m-1,m);
	reverse(arr, m, 5, len -= m);
}
int main() {
	int arr[] = { 1,2,3,4,5,6 };
	int len = sizeof(arr) / sizeof(arr[0]);
	adjust_array(arr,6,2);
	//reverse(arr, 0, 5,6);
	for (int i = 0; i < len; i++) {
		printf("%3d", arr[i]);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值