循环分支、字符串习题(水仙花数、字符串左旋)

目录

1. 求前n项a的和

2. 打印出1-1000之间所有的水仙花数

3. 使得数组内奇数全部位于偶数前面

4. 智力题:喝汽水问题

5. 智力题:找凶手问题

6. 字符串左旋

7. 判断一个字符串是否为另外一个字符串旋转之后的字符串


1. 求前n项a的和

如:2+22+222+2222+22222

	int a = 2; int n = 2;
	int sum = 0;
	int i = 0; 
	int j = 0;
	for(i=1; i<=n; i++)
	{
		int ret = 0;
		for(j=0; j<i; j++)
		{
			ret += a * (pow(10,j));//注意:次方的书写格式;
		}
		sum += ret;
	}
	printf("sum is %d\n",sum);

//解法二:以上可以简化,222 = 2+22*10
	int a = 2; int n = 2;
	int sum = 0;
	int i = 0; 
	int ret = 0;
	for(i=1; i<=n; i++)
	{
		ret = a + ret *10;//ret用来保存中间数;
		sum += ret;
	}
	printf("sum is %d\n",sum);
	

2. 打印出1-1000之间所有的水仙花数

水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI)、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrong number),水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身。例如:1^3 + 5^3+ 3^3 = 153。

int Is_n(int i){
	int a = 0;
	while(i != 0){
		i = i/10;
		a++;
	}
	return a;}

	//先判断这是几位数;再判断n次幂之和是否等于这个数;
int main(){
	int i = 0;
	int n = 0;
	for(i = 1; i<=1000; i++){
		int tmp = i;
		int sum = 0;
		n = Is_n(i);//判断是几位数;
		while(tmp != 0){
			sum += pow(tmp%10,n);
			//i = i/10;//i的值会变,创建一个临时变量tmp
			tmp = tmp/10;
		}
		if( sum == i){
			printf("%d ",i);
		}// end if
	}// end for
}

3. 使得数组内奇数全部位于偶数前面

冒泡排序的思想

int Is_odd_even(int i)
{
	if(i%2 == 0)
		return 0;//偶数返回0
	else
		return 1;//奇数返回1
}
   
    int arr[] = {1, 2 ,3, 4, 5, 6, 7, 8};
	int i = 0;
	int sz = sizeof(arr)/sizeof(arr[0]);
	for(i=0; i<sz-1; i++)//冒泡排序的思想;
	{
		int j = 0;
		for(j = i; j<sz-1; j++)
		{
			if(Is_odd_even(arr[j])<Is_odd_even(arr[j+1]))//偶数位0,奇数为1
			{
				int tmp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = tmp;
			}
		}
	}
	for(i = 0; i<sz; i++)
	printf("%d ",arr[i]);

4. 智力题:喝汽水问题

一瓶一元,两个空瓶可以换一瓶汽水,20元可以喝多少瓶

	int money = 20;
	//第一次买回来的水
	int total = money;
	int empty = money;
	//换回来的水
	while(empty/2)
	{
		total += empty/2;
		empty = empty/2 + empty%2;
	}
	printf("%d\n",total);

5. 智力题:找凶手问题

    a说:不是我;
    b说:是c
    c说:是d
    d说:c说的不对
    以上3句真话,1句假话
    以上四个语句产生0或者1,依次假设凶手,加起来等于3则满足题意

	char killer = 0;
	for (killer = 'A'; killer <= 'D'; killer++)
	{
		if (  (killer != 'A') 
            + (killer == 'C') 
            + (killer == 'D') 
            + (killer != 'D') 
            == 3 )
		{
			printf("killer is %c\n", killer);
		}
	}
	

智力题训练:可参考牛客网-专项训练-智力题
赛马问题、烧香问题等

6. 字符串左旋

实现一个函数,可以左旋字符串中的k个字符。
例如:ABCD左旋一个字符得到BCDA;ABCD左旋两个字符得到CDAB

(1)暴力求解法

void Left_rotate(char arr[])//左旋一次
{
	int sz = strlen(arr);
	char tmp = arr[0];
	int j = 0;
	for(j = 0; j<sz-1; j++)
	{
		arr[j] = arr[j+1];
	}
	arr[sz-1] = tmp;
}

void Right_rotate(char arr[])//右旋一次
{
	int sz = strlen(arr);
	char tmp = arr[sz-1];
	int j = 0;
	for(j = sz-1; j>0; j--)
	{
		arr[j] = arr[j-1];
	}
	arr[0] = tmp;
}

void Reverse_L_R(char arr[], void(*p)(char[]), int n)//左旋n次
{
	int i = 0;
	for(i = 0; i<n; i++)
	{
		(*p)(arr);
	}
}

	char arr[] = "abcd";
	int n = 2;
	void(*p)(char arr[]) = &Left_rotate;
	Reverse_L_R(arr, p, n);//回调函数
	printf("%s ",arr);

(2)三步反转法

void string_left_rotate(char* str, int k)
{
	int n = strlen(str);
	assert(str);
	//三次逆序后达到左旋的效果;
	reverse(str, str+k-1);//逆序左边
	reverse(str+k, str+n-1);//逆序右边
	reverse(str, str+n-1);//逆序整体
}

	char arr[] = "abcd";
	int n = 2;
	string_left_rotate(arr, n);
	printf("%s ",arr);

7. 判断一个字符串是否为另外一个字符串旋转之后的字符串

例如:给定s1 = AABCD和s2 = BCDAA,返回yes
给定s1 = abcd和s2 = ACBD,返回no

(1)穷举法

	char arr1[] = "abcde";
	char arr2[] = "bcdea";
	int i = 0; int sz = strlen(arr1);
	for(i=0; i<=sz; i++)
	{
		//可以利用上一题的左旋函数
		//string_left_rotate(arr2, i);//这里不能用i,每次旋转之后arr2都变了
		string_left_rotate(arr2, 1);//用1就行,在上一次旋转的基础上旋转
		if(strcmp(arr2, arr1)==0){
			printf("yes\n");
			break;}
	}
	if(i > sz)
		printf("no\n");

(2)如果是旋转串,那么arr2肯定是arr1+arr1的子串

	char arr1[30] = "abcde";
	char arr2[30] = "bcdea";//前提要保证两个字符串长度相等
	int sz = strlen(arr1);
	char * ret;
	//1. arr1字符串的后边追加一个arr1
	//strcat(arr1, arr2);//在arr1后面arr2
	//printf("%s ",arr1);
	strncat(arr1,arr1, sz);//该函数用于追加相同的字符串
	//2. 判断arr2是否为追加后arr1的子串
	ret = strstr(arr1, arr2);//该函数用于判断arr2是否为arr1的子串,是则返回子串起始字符地址,不是则返回NULL
	if(ret == NULL)
		printf("no\n");
	else
		printf("yes\n");
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值