C语言之练习题

发布于:2024-10-17 ⋅ 阅读:(11) ⋅ 点赞:(0)

在这里插入图片描述

欢迎来到我的:世界

希望作者的文章对你有所帮助,有不足的地方还请指正,大家一起学习交流 !😊


前言


内容

第一题:子数组最大平均数


OJ地址


在这里插入图片描述

思路:
暴力求解法:设置两个指针,从开头向后找k个数值求平均值,继续往后遍历,找出最大平均值;注意:可能会显示时间超时
滑动窗口法:可以先将0~k个数值的看作是一个窗口,计算出这个窗口中的所有元素的和sum,并且记录所有元素和的最大值maxsum,再让这个窗口往后移动一个数字计算窗口的和最大值,依次类推,等窗口走完,将得到的最大和maxsum / k =最大的平均值
动图演示:
在这里插入图片描述

暴力求解法:

double findMaxAverage(int* nums, int numsSize, int k) {
    
    //设置最大平均值:
    double maxaverage=-10000;
    double x=k;//把int类型的k转化为double类型
    for(int i=0;i<=numsSize-k;i++)
    {
        double sum=0;
        //往后找k个数值
        for(int j=i;j<k+i;j++)
        {
            sum+=nums[j];
        }
        sum=sum/x;//求平均值
        if( sum >maxaverage )
            maxaverage=sum;//找出最大平均值
    }
    return maxaverage;
}

滑动窗口法:

double findMaxAverage(int* nums, int numsSize, int k) {
    int maxsum = 0;
    int sum = 0;
    //设置窗口
    for (int i = 0; i < k; i++) {
        sum += nums[i];
    }
    maxsum = sum;
    //窗口移动
    for (int i = k; i < numsSize; i++) {
        sum = sum - nums[i - k] + nums[i];
        maxsum = fmax(sum, maxsum);//fmax函数是得出两者中的较大值
    }
    return (double)maxsum / k;//不要忘记强制类型转换
}

第二题:回文数


OJ地址


在这里插入图片描述

思路:
双指针法:将整形数值x转化为字符串类型,可以使用sprintf函数,字符串可以运用两个指针进行前后同时遍历,只要不同就返回false

双指针法:

bool isPalindrome(int x) {
    if(x<0)//凡是小于0的不可能是回文数
        return false;
    if(x==0)
        return true;
    //将整形类型转化为字符串类型
    char arr [100];
    sprintf(arr,"%d",x);
    //计算整形的位数
    int count=0;
    while(x)
    {
        x/=10;
        count++;
    }
    //设置两个指针进行前后遍历
    int i=0;
    int j=count-1;
    //开始遍历找不同
    while(i<j)
    {
        if(arr[i++]!=arr[j--])
        {
            return false;
        }
    }
    return true;
}

第三题:找到两个单身狗


介绍:在一串数组中找到单独的两个数字,其余数都是成对出现的;如:arr[6]={1,2,1,3,2,4}两个单身狗存到诞生狗数组中dog[2]:就是这样dog[2]={3,4}

思路:运用位运算:按位异或操作,但是如果是按照一个单身狗的解题方法是不可以的,因为最后会有两个值不同,但是我们可以将这两个数拆开放在不同数组中不就解决了,但是怎么将这个数组分成两个数组呢? 又根据什么进行分法呢?:所以带着这两个问题我们继续向下看:
可以发现按位异或^操作的规律:
3(011)^4(100)=111,其实就是将这两个数不同的位变成了1
7(111)^6(110)=001,就是将这两个数二进制位不同的变成的了1:
所以我们可以推出:可以根据这两个单独数的位将进行分组
如:如果在这个数组中arr[6]={1,2,1,6,2,4},两个单身狗6 4,进行按位异或^操作后6^4 = 010这代表64的二进制位从右边数第j=2位不一样,让每个数的第j&1就可以分别出他们,可以根据这点将这两个单独的数分开。
如图:在这里插入图片描述
代码实现:

void Findalone(int arr[], int n)
{
	int a = 0;
	for (int i = 0; i < n; i++)
	{
		a ^= arr[i];
	}
	int num1[100] = { 0 };
	int num2[100] = { 0 };

	//找到二进制第j位上不同;
	int j = 0;
	for (j = 0; j < 32; j++)
	{
		//找到从右边数第j位,后直接跳出循环
		if ( (a >> j) == 1)
			break;
	}
	
	//创建两个指针分别遍历两个数组
	int q1 = 0;
	int q0 = 0;

	//二进制的j位,不同的分成两个数组中,
	//  就可以将两个单独的数分离开,再去分别求每个数组的单独数
	for (int i = 0; i < n; i++)
	{
		if (((arr[i] >> j) & 1 )== 1)
		{
			num1[q1++] = arr[i];
		}
		else
		{
			num2[q0++] = arr[i];
		}
	}
	
	//运用找单身狗的方法,找单独数
	int k = 0;
	for (int i = 0; i < q1; i++)
	{
		k ^= num1[i];
	}
	printf("其中一个单身狗是:%d\n", k);

	k = 0;
	for (int i = 0; i < q0; i++)
	{
		k ^= num2[i];
	}
	printf("另一个单身狗是:%d\n", k);
}

第四题:一道面试笔试题

请问该段代码输出的结果是什么?:
在这里插入图片描述

思路:
这题看似很复杂,其实很复杂 * _ *
先进行分析:一级指针数组c,里面应该存存了四个地址,地址存放的是对应的字符串。(地址就是指针)
在这里插入图片描述
再分析二级指针数组cp:二级指针存放了四个一级指针的地址,指针指向如图所示:
在这里插入图片描述>再分析三级指针cpp三级指针比较特殊,其存放一个地址,存放了二级指针cp地址;>如图:在这里插入图片描述

开始分析第一个语句:printf("%s\n", **++cpp);
首先优先级:* < ++, 关于优先级:只需要记住:++--(),[]的优先级就是最高的;
所以这里 ++先和cpp结合,在进行解引用操作*,
所以**++cpp 相当于 *(*(++cpp)),++cpp相当于(cp+1);
然后解引用操作*:就是根据这块地址找到这块地址所存的内容
第一个解引用操作*(++cpp)找到cp数组的第二个元素(其中每一个元素都是一个二级指针地址)所存的内容是c数组的第三个元素;
第二次解引用*(*(++cpp))就是指c数组的第三个元素中所存的内容:字符串“POINT”的首元素地址,所以最后打印就是打印从开头打印:POINT
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/611195503b53406ba2100bf
printf("%s\n", **++cpp);结果为POINT

分析第二个语句:printf("%s\n", *-- * ++cpp + 3);
可看成这样:(*(--*(++cpp))) - 3 注意此时cpp应该是指向cp数组的第二个元素,*(++cpp) 此时cpp指针往后走一步后到cp数组的第三个元素,再进行解引用,根据cp第三个元素的地址,找到c数组中第二个元素,在看 *(--*(++cpp))先执行--操作,此时又指向c数组第一个元素,在进行解引用,找到字符串ENTER首元素地址,此时还没结束,还要+3操作,就是从字符串往后找三个字节,找到了E,所以此时打印就打印出ER;
在这里插入图片描述
printf("%s\n", *-- * ++cpp + 3);结果为ER

开始分析第三句话:printf("%s\n", *cpp[-2] + 3);
注意此时cpp开始就指向cp数组的第三个元素;
看到 cpp[-2] 就等于*(cpp-2)该操作下来,应该为:cpp移动后指向cp的第一个元素,在进行解引用,找到了c数组的第四个元素,此时再进行解引用找到了字符串FIRST,在进行+3就是和上面的操作一样,找到字符S,就从S开始打印,出:ST
在这里插入图片描述
printf("%s\n", *cpp[-2] + 3);结果为ST

分析最后一句话:printf("%s\n", cpp[-1][-1] + 1);
看到cpp[-1][-1] 就等于 *(*(cpp-1)-1),操作步骤为-1操作后cpp指向cp数组的第二个元素,解引用找到c数组第三个元素,在-1操作后,指向c数组的第二个元素,解引用找打字符串NEW,在进行+1操作,找到字符E,就从E开始打印出:EW
在这里插入图片描述
printf("%s\n", cpp[-1][-1] + 1);结果为:EW


请添加图片描述


总结


到了最后:感谢支持

我还想告诉你的是:
------------对过程全力以赴,对结果淡然处之
也是对我自己讲的