【C语言进阶】题目练习(3)
目录
题目1:左旋k个字符
思路1:
代码1:
思路2:
代码2:
题目2:杨氏矩阵
思路:
代码:
题目3:指针选择题
答案:
题目4: 回调函数的选择题
答案:
题目5:判断左旋或右旋
思路1:
代码1:
思路2:
代码2:
题目6:函数设计选择题(多选)
答案:
题目7:函数参数设计选择题
答案:
题目7:矩阵转置
分析:
题目8:上三角矩阵判定
分析:
代码:
题目9:有序序列判断
分析:
题目1:左旋k个字符
思路1:
①左旋一个字符,只需要将a取出,剩下的元素依次前移,把a放到最后即可。
②将多个字符的旋转分化成第一个字符多次旋转。
③总结:先旋转一个字符,若有n个字符,则循环n次即可。
④后续可以优化,如果输入的n大于数组元素个数,就不用左旋。
代码1:
#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:
#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的坐标。
代码:
#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:
#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);// 长度不同,直接返回0if (len1 != len2) return 0;// s1每次左旋一个字符就判断是不是s2for (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左旋后能否得到s2return 0;
}
思路2:
使用库函数来实现,在abcdef后面追加一个abcdef,如此一来abcdefabcdef涵盖了所有的子串,这时候只需要使用库函数来判断是否是子串即可!
代码2:
#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左旋后能否得到s2return 0;
}
注意:尽量不要使用strcat自己追加自己,这样会把\0覆盖可能导致死循环。
题目6:函数设计选择题(多选)
答案:
BD
B:数组名传参,数组名是首元素的地址,首元素的类型是char*,要存放它的地址类型应该是char**所以B正确;
D:形参实参一致,正确。
题目7:函数参数设计选择题
答案:
C
arr是首元素的地址,arr的首元素是一个一维数组,可以使用数组指针指向一个5个int类型的数组,选C
题目7:矩阵转置
描述
分析:
二维数组本身就是按序排列存储,我们按照行读取数组之后,只需要按照列输出即可。
需要按照列的取值作为外层循环,行的取值作为内层循环
#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即可。
代码:
#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代表了全是相等的情况。
#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;
}