c刷题【五】

目录

喝汽水问题

 变种水仙花

奇偶分离

判断有序序列

 有序序列合并

X型图案 

箭型图案 

猜排名

 猜凶手


喝汽水问题

1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水(编程实现)。

设置三个变量,金钱,空瓶数和汽水数。其中初始汽水数和空瓶为金钱总数。利用空瓶回收进行循环,需要注意当空瓶为奇数时需要保留下来以便进行下一次兑换。

int money = 0;
	int total = 0;
	int empty = 0;
	scanf("%d", &money);
	 total = money;
	 empty = money;
	 while (empty >= 2)
	 {
		 total += empty / 2;
		 empty = empty / 2 + empty % 2;
	 }
	 printf("%d\n", total);

我们可以通过多组输入发现金钱和汽水数有一个确定的规律: total = moeny*2 +1 

 变种水仙花

 对于乘号前面的数,可通过/10,/100...获取,乘号后面的数通过%10,%100...获取,结束条件是不超过当前位数。

#include <stdio.h>
#include <math.h>
int main() {
    int i = 0;
  for(i = 10000; i <= 99999; i++)
  {
    int sum = 0;
    int j = 0;
    for(j = 1;j<=4;j++)
    {
        int ret = (int)pow(10,j);
        sum += (i%ret) * (i/ret);
    }
    if(sum == i)
    printf("%d ",sum);
  }
    
    return 0;
}

奇偶分离

提供一种时间复杂度最低的做法——双指针遍历左边遇到偶数,右边遇到奇数双双交换,当left>=right时,没有必要再交换。

void move_even_odd(int arr[], int sz)
{
	int left = 0;
	int right = sz - 1;

	while (left < right)
	{
		//从前往后找一个偶数停下来
		while ((left < right) && (arr[left] % 2 == 1))
		{
			left++;
		}
		//从后往前找一个奇数停下来
		while ((left < right) && (arr[right] % 2 == 0))//
		{
			right--;
		}
		if (left < right)
		{
			int tmp = arr[left];
			arr[left] = arr[right];
			arr[right] = tmp;
			left++;
			right--;
		}
	}
}

需要注意避免越界和全奇全偶的情况,在移动和交换前都要判断left是否小于right。

判断有序序列

有序序列判断_牛客题霸_牛客网

设置两个开关变量,根据升序和降序分别处理,要单独拎出其中有相等的情况(1 1 2 2 4), 和全等的情况(1 1 1 1 1)。

#include <stdio.h>

int main() {
    int n = 0;
    scanf("%d",&n);
    int arr[n];
    int i=0;
    int flag1 = 0;//升序
    int flag2 = 0;//降序
    for(i=0;i< n;i++)
    {
        scanf("%d", &arr[i]);
    }
    for(i=0;i<n-1;i++)
    {
       if(arr[i] < arr[i+1])
        flag1 = 1;
        if(arr[i] > arr[i+1])
        flag2 = 1;
        //等于不做处理
    }
    if(flag1 + flag2 <=1)//包含数据全等的情况
    printf("sorted\n");
    else
     printf("unsorted");
    return 0;
}

 有序序列合并

方法一:两个数组合并成一个数组进行快排。

#include <stdio.h>      
#include <stdlib.h>     
int compare(const void* a, const void* b)
{
    return *(int*)a - *(int*)b;
}
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    int arr1[n] ;
    int arr2[m] ;
    int arr3[n+m];//初始化为0
    int i = 0;
    int j = 0;
    for (i = 0; i < n; i++)//自己设置字符串数据
    {
        scanf("%d", &arr1[i]);//别忘了取地址
    }
    for (i = 0; i < m; i++)
    {
        scanf("%d", &arr2[i]);
    }
    for (i = 0; i < n+m; i++)
    {
        if (i < n)
            arr3[i] = arr1[i];
        else
        {
            arr3[i] = arr2[j];
            j++;
        }
        
    }
    qsort(arr3, n+m, sizeof(int), compare);
    for (i = 0; i < n+m; i++)
    {
        printf("%d ", arr3[i]);
    }
    return 0;
}

方法二:利用指针比较大小遍历数组,再输出数组剩余部分。

#include <stdio.h>          
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    int arr1[n];
    int arr2[m];
    int i = 0;
    int j = 0;
    for (i = 0; i < n; i++)//自己设置字符串数据
    {
        scanf("%d", &arr1[i]);//别忘了取地址
    }
    for (i = 0; i < m; i++)
    {
        scanf("%d", &arr2[i]);
    }
    i = 0;
    j = 0;
    while(i<n && j<m)
    {
        if(arr1[i] < arr2[j])
        {
            printf("%d ",arr1[i]);
            i++;
        }
        else
        {
            printf("%d ",arr2[j]);
            j++;
        }
    }
    if(i == n)
        {
            for(;j<m;j++)
            printf("%d ",arr2[j]);
        }
        else 
        {
             for(;i<n;i++)
            printf("%d ",arr1[i]);
        }
    return 0;
}

X型图案 

X形图案_牛客题霸_牛客网

规律是二维数组的主对角线和副对角线,主对角线行列相等,副对角线行列和为一个定值

#include<stdio.h>
int main()
{
    int i = 0,n = 0;
    while (scanf("%d", &n) == 1)
    {
        for (i = 0; i < n; i++)//打印出X图形其实就是模拟二维数组,规律是对角线输出
        {
            int j = 0;
            for (j = 0; j < n; j++)
            {
                if (i == j || i+j == n-1)
                    printf("*");
               else
                    printf(" ");//剩余的直接为 ‘ ’
            }
            printf("\n");
        }
    }
    return 0;
}

箭型图案 

箭形图案_牛客题霸_牛客网

要点:分上半和下半打印,注意空格可以两个一打印,灵活利用行(i)的变化打印。 

#include<stdio.h>
int main()
{
    int i = 0,n = 0;
    while (scanf("%d", &n) == 1)
    {
       
        for (i = 0; i < n+1; i++)
        {
            int j = 0;
            for (j = 0; j < n-i; j++)
            {
                printf("  ");
            }
            for(j = 0;j<=i;j++)
            {
                printf("*");
            }
             printf("\n");
        }
        for (i = 0; i <n; i++)
        {
            int j = 0;
            for (j = 0; j <= i; j++)
            {
                printf("  ");
            }
            for (j = 0; j < n-i; j++)
            {
                printf("*");
            }
            printf("\n");
        }
    }
    return 0;
}

猜排名

5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果:

A选手说:B第二,我第三;

B选手说:我第二,E第四;

C选手说:我第一,D第二;

D选手说:C最后,我第三;

E选手说:我第四,A第一;

逻辑推断题,可以利用穷举法, 比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。说对一半可以译为1+0 == 1,每位可以译为&&。

	int a = 0;
	int b = 0;
	int c = 0;
	int d = 0;
	int e = 0;
	for (a = 1; a <= 5; a++)
	{
		for (b = 1; b <= 5; b++)
		{
			for (c = 1; c <= 5; c++)
			{
				for (d = 1; d <= 5; d++)
				{
					for (e = 1; e <= 5; e++)
					{
						if (((b==2) + (a==3) == 1) &&
							((b==2) + (e==4) == 1) &&
							((c==1) + (d==2) == 1) &&
							((c==5) + (d==3) == 1) &&
							((e==4) + (a==1) == 1))
						{
							if((a * b * c * d * e == 120) &&(a+b+c+d+e==15))
								printf("a=%d b=%d c=%d d=%d e=%d\n", a, b, c, d, e);
						}
					}
				}
			}
		}
	}

可以看到在输出结果时我添加了判断条件,是因为结果有多个名次重名了,因为遍历时并没有考虑名次占用问题,所以我们根据每个排名的独特性添加判断筛选出不重复的排名即可。

 猜凶手

日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。

以下为4个嫌疑犯的供词:

A说:不是我。

B说:是C。

C说:是D。

D说:C在胡说。

已知3个人说了真话,1个人说的是假话。

现在请根据这些信息,写一个程序来确定到底谁是凶手。

先假定一人说的是假话。3真话,1假话:4人逻辑判断之和为3。

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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小C您好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值