【C语言进阶】题目练习(3)

目录

题目1:左旋k个字符

思路1:

代码1:

思路2:

代码2:

题目2:杨氏矩阵

思路:

代码:

题目3:指针选择题

答案:

[题目4: 回调函数的选择题](#题目4: 回调函数的选择题)

答案:

题目5:判断左旋或右旋

思路1:

代码1:

思路2:

代码2:

题目6:函数设计选择题(多选)

答案:

题目7:函数参数设计选择题

答案:

题目7:矩阵转置

分析:

题目8:上三角矩阵判定

分析:

代码:

题目9:有序序列判断

分析:


题目1:左旋k个字符

思路1:

①左旋一个字符,只需要将a取出,剩下的元素依次前移,把a放到最后即可。

②将多个字符的旋转分化成第一个字符多次旋转。

③总结:先旋转一个字符,若有n个字符,则循环n次即可。

④后续可以优化,如果输入的n大于数组元素个数,就不用左旋。

代码1:

cpp 复制代码
#include<stdio.h>
#include<string.h>
// 1.左旋字符串

void turnLeft(char* str,int n) 
{
    // 若n非常大,需要进行取模
	n %= strlen(str);
    // 旋转几个字符就循环几次
	while (n--) 
	{
		// 旋转第一个字符
		char tmp = *str;
		for (int i = 0; i < strlen(str) - 1;i++) 
		{
			str[i] = str[i + 1];
		}
		str[strlen(str) - 1] = tmp;
	}
}


int main() 
{
	char str[] = "ABCDE";
	turnLeft(str, 3);
	printf("%s\n", str);
}

思路2:

①将数组分成两个部分:旋转区域和非旋转区域。

②对这两个区域分别逆序。

③整体逆序,得到了旋转个字符的效果。

代码2:

cpp 复制代码
#include<stdio.h>
#include<string.h>
void turnLeft_2(char* str, int n) 
{
	n %= strlen(str);
	// 旋转区逆序
	reverse_str(str, str + n - 1);
	// 非旋转区逆序
	reverse_str(str + n, str + strlen(str) - 1);
	//整体逆序
	reverse_str(str, str + strlen(str) - 1);
}



int main() 
{
	char str[] = "ABCDE";
	turnLeft_2(str, 3);
	printf("%s\n", str);
}

题目2:杨氏矩阵

思路:

要在二维数组中查询某个数,遍历即可,但是要求时间复杂度为O(N),就要思考一下了。

我们可以这样想:每次和二维数组右上角的数字进行比较,右上角的数字是本行最大的数字,如果比右上角的数字还要大,说明要查找的数字不在这一行,需要往下继续查找。

同理右上角的数字是同列最小的,如果待查找的数字是2,2 < 3,此刻2一定不在3那一列。

①设置行列初始值,从第0行,第2列(若是3*3的矩阵)开始;

②行不能大于2,列不能小于0;

(1)若num比右上角小,说明不在此列,需要列--;

(2)若num比右上角大,说明不在此行,需要行++;

(3)若以上都不成立,那么num就找到了,此时的col、row就是num的坐标。

代码:

cpp 复制代码
#include<stdio.h>
#include<string.h>
void yanghuiSquare(int arr[3][3],int num)
{
	// 从右上角开始
	int col = 2;
	int row = 0;
	// 行坐标和列坐标的限制
	while (row < 3 && col > 0) 
	{
		// 不在这一行
		if (num > arr[row][col]) 
		{
			row++;
		}
		else if (num < arr[row][col]) // 不在这一列
		{
			col--;
		}
		else 
		{
			printf("%d的下标在(%d,%d)",num,row,col);
			return;
		}
	}
    printf("%d未在矩阵中找到\n", num);
}
int main() 
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
	yanghuiSquare(arr,5);
}

题目3:指针选择题

答案:

C

A:这是一个数组,数组的每一个元素是一个函数指针,错误。

B:这是一个指针,指向一个函数,函数返回值是int[10],错误。

C:这是一个指针,去掉(*p)剩下int(*[10])(int),这是一个数组有10个元素,每一个元素的类型是函数指针,形参为int*,正确。

D:这是一个指针,指向的是int ((int*)[10]),这是一个函数,错误。

题目4: 回调函数的选择题

答案:

D

回调函数是调用函数指针指向的函数。

题目5:判断左旋或右旋

思路1:

每次旋转一个字符之后需要和另外一个字符串比较, 如果相同那就直接返回并输出即可。

代码1:

cpp 复制代码
#include<stdio.h>
#include<string.h>
int is_left(char s1[], char s2[])
{
	int len1 = strlen(s1);
	int len2 = strlen(s2);
	int cnt = 0;
	char* p = s1;
	char tmparr[10] = { 0 };
	strcpy(tmparr, s1);
	// 长度不同,直接返回0
	if (len1 != len2) return 0;
	// s1每次左旋一个字符就判断是不是s2
	for (int i = 0; i < len1; i++)
	{
		cnt++;
		char tmp = s1[0];
		for (int i = 0; i < len1 - 1; i++)
		{
			s1[i] = s1[i + 1];
		}
		s1[len1 - 1] = tmp;
		// 左旋完毕判断
		if (!strcmp(s1, s2))
		{
			printf("%s是由%s左旋%d次得到的!\n", s2, tmparr, cnt);
			return 1;
		}
	}

}

int main()
{
	char s1[] = { "abcdef" };
	char s2[] = { "cdefab" };
	
	is_left(s1, s2); // 判断s1左旋后能否得到s2
	return 0;
}

思路2:

使用库函数来实现,在abcdef后面追加一个abcdef,如此一来abcdefabcdef涵盖了所有的子串,这时候只需要使用库函数来判断是否是子串即可!

代码2:

cpp 复制代码
#include<stdio.h>
#include<string.h>
int is_left_2(char s1[], char s2[]) 
{
	int len = strlen(s1);
	strncat(s1,s1,len);
	if (strstr(s1, s2)) 
	{
		printf("左旋能得到");
	}
	else 
	{
		printf("左旋不能得到");
	}
}
int main()
{
	char s1[20] = { "abcdef" };
	char s2[] = { "cdefab" };
	
	is_left_2(s1, s2); // 判断s1左旋后能否得到s2
	return 0;
}

注意:尽量不要使用strcat自己追加自己,这样会把\0覆盖可能导致死循环。

题目6:函数设计选择题(多选)

答案:

BD

B:数组名传参,数组名是首元素的地址,首元素的类型是char*,要存放它的地址类型应该是char**所以B正确;

D:形参实参一致,正确。

题目7:函数参数设计选择题

答案:

C

arr是首元素的地址,arr的首元素是一个一维数组,可以使用数组指针指向一个5个int类型的数组,选C

题目7:矩阵转置

描述

分析:

二维数组本身就是按序排列存储,我们按照行读取数组之后,只需要按照列输出即可。

需要按照列的取值作为外层循环,行的取值作为内层循环

cpp 复制代码
#include <stdio.h>

int main() {
    int n = 0;
    int m = 0;
    scanf("%d %d", &n, &m);
    int arr[n][m];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d", &arr[i][j]);
        }
    }
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
           printf("%d ",arr[j][i]);
        }
        printf("\n");
    }
    return 0;
}

题目8:上三角矩阵判定

分析:

我们注意到,下三角的区域的列索引小于行索引,所以我们只需要判断此区域的数值是否为0即可。

代码:

cpp 复制代码
#include <stdio.h>

int main() {
    int num = 0;
    scanf("%d", &num);
    int arr[num][num];
    for (int i = 0; i < num; i++ ) {
        for (int j = 0; j < num; j++ ) {
            scanf("%d", &arr[i][j]);
        }
    }
    int flag = 1;// 是上三角
    for (int i = 0; i < num; i++ ) {
        for (int j = 0; j < i; j++ ) { // 只遍历下三角区域
            if( arr[i][j] !=0)
            {
                flag = 0;
                break;
            }
        }
    }
    if(flag)
    {
        printf("YES");
    }else
    {
        printf("NO");
    }
    return 0;
}

题目9:有序序列判断

分析:

这里的有序分为正序和降序,所以设置两个变量:flag1代表是否升序,flag2代表是否降序,一个有序的数列,要么是升序要么是降序,所以flag1和flag2只能有一个是1。

这里需要注意的是111112,这个数列,所以要分为三种情况,此时flag的和要小于等于1,等于一说明要么是正序要么是降序,小于1代表了全是相等的情况。

cpp 复制代码
#include <stdio.h>

int main() {
    int num = 0;
    scanf("%d",&num);
    int arr[num];
    for (int i = 0; i < num; i++) {
        scanf("%d",&arr[i]);
    }
    int flag_1 = 0;// 升序
    int flag_2 = 0; // 降序
    for (int i = 0; i < num - 1; i++) {
        if(arr[i] < arr[i+1])
        {
            flag_1 = 1;
        }else if(arr[i] > arr[i+1]){
            flag_2 = 1;
        }else
        {
             // 什么也不做    
        }
    }
    if((flag_1 + flag_2) <=1 )// 有序
    {
        printf("sorted");
    }else {
         printf("unsorted");
    }
    return 0;
}
相关推荐
归云鹤25 分钟前
设计模式五:桥模式(Bridge Pattern)
算法·设计模式·桥接模式
瓜子三百克1 小时前
Swift6.1 - 基础知识1: 简单值、控制流、函数和闭包
开发语言·swift
froginwe111 小时前
Swift 条件语句
开发语言
2301_794461572 小时前
牛客-倒置字符串
算法·leetcode·动态规划
COSMOS_*2 小时前
2025最新版 Go语言&Goland 专业安装及配置(超详细)
开发语言·后端·golang·go
云青山水林2 小时前
板子 5.29--7.19
数据结构·算法
Kiri霧3 小时前
Kotlin方差
android·开发语言·kotlin
子豪-中国机器人4 小时前
2025年7月19日,二维矩阵
数据结构·c++·算法
Kiri霧4 小时前
Kotlin内联函数
android·开发语言·微信·kotlin
gjf05_054 小时前
人该怎样活着呢?55
学习