当前位置: 首页 > news >正文

练习(杨辉三角、字符串旋转)

一、

以下程序执行的结果:
 

int main()
{//0~255unsigned char a = 200;//00000000000000000000000011001000//11001000 - a 截断unsigned char b = 100;//00000000000000000000000001100100//01100100 - b    unsigned char c = 0;c = a + b;//11001000 - a//01100100 - b//提升//00000000000000000000000011001000 - a(无符号类型)    //00000000000000000000000001100100 - b//00000000000000000000000100101100 - a+b 300(正数 原码、补码、反码相同)//00101100 - c 44 (c是无符号字符类型,高位默认补0,原码、反码、补码相同)printf("%d %d",a+b,c);//300  44return 0;
}

二、猜名次

题目内容 :
5位运动员参加了代米台跳水比赛,有人让他们预测比赛结果
A选手说 : B第二,我第三;
B选手说:我第二,E第四:
C选手说:我第一,D第二
D选手说 : C最后,我第三
E选手说 : 我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。

思路:a,b,c,d,e都假设一遍(每一个人都假设为第 1 2 3 4 5 名)

至少有一个为真:1+0=1 0+1=1;例如A选手 (b == 2)+(a == 3) == 1 

int main()
{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){printf("a=%d b=%d c=%d d=%d e=%d\n",a,b,c,d,e);}}}}}}return 0;
}

如果我们按以上程序打印,会出现许多种可能,其中还会出现重复现象,例如,出现a和e同时是第一名的情况,其中只有一个正确的答案没有重复

由于1*2*3*4*5==120,我们可以利用这条式子来输出正确的答案

int main()
{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)printf("a=%d b=%d c=%d d=%d e=%d\n",a,b,c,d,e);}}}}}}return 0;
}

三、猜凶手

题目内容 :
日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个。
以輸下为4个嫌疑犯的供词 :
A说:不是我。
B说 : 是C。
C说 : 是D。
D说 : C在胡说
已知3个人说了真话,1个人说的是假话。
现在请根据这些信息,写一个程序来确定到底谁是凶手。
思路:每个人都假设一遍(假设为凶手,看看是否能符合描述)

        () + () + () + () == 3 (有三个说的为真,1)

int main()
{char killer = 0;for(killer= a';killer<='d';killer++){if((killer != 'a')+(killer == 'c')+(killer == 'd')+(killer != 'd') == 3){printf("凶手是%c\n",killer);//c}}return 0;
}

四、杨辉三角

在屏幕上打印杨辉三角

        1
      1  1
    1  2  1
  1  3  3  1
1  4  6  4  1
………………

int main()
{int arr[10][10] = {0};printf("请输入杨辉三角的行数:>");int n = 0;scanf("%d",&n);int i = 0;for(i=0;i<n;i++){int j = 0;for(j=0;j<=i;j++)//只需要打印对角线及以下的部分{if(j==0)arr[i][j] = 1;if(i==j)arr[i][j] = 1;if(i>=2 && j>=1)//从第三行开始,每个中间元素等于上一行相邻两个元素之和arr[i][j] = arr[i-1][j-1] + arr[i-1][j];}}for(i=0;i<n;i++){int j = 0;int space = 0;for(space=0;space<(n-i-1)*2;space++){printf(" ");}for(j=0;j<=i;j++){printf("%4d ",arr[i][j]);}printf("\n");}return 0;
}

每行前导空格数采用(n-i-1)*2的计算方式,是为了确保杨辉三角在输出时能居中对齐,形成美观的金字塔形状。

1.居中对齐
杨辉三角的每一行需要逐层缩进,使得所有行的中心线与最后一行的中心对齐

假设:·总行数为 n,最后一行的元素最多(共n 个元素)。

每个元素占4字符宽度(通过 %4d 格式实现),因此最后一行的总宽度为 4n。
最后一行的中心位置2n处(总宽度4n 的一半)。
为了让当前行 i 的中心位置与最后一行的中心对齐,需要动态计算前导空格数

2.公式推导
当前行 i 的元素数量: i+1个。
当前行的总宽度: 4*(i+1)字符。
当前行的中心位置:  2*(i+1)(当前行总宽度的一半)。
为使当前行中心与最后一行的中心2n对齐:

前导空格数 + 当前行中心位置 = 最后一行中心位置
即:
前导空格数 + (i+1)*2 = 2n
则:
前导空格数 = 2n - 2*(i+1) = (n-i-1)*2

元素之间的空格由 %4d 控制
代码中使用 printf("%4d",arr[i][j])打印每个元素,其中 %4d 表示:。每个数字占用4个字符宽度,右对齐。不足4位的数字:左侧用空格填充,例如数字 1会输出为…1(·表示空格)。·相邻元素:两个 %4d格式符连写时,元素之间的间隔为3个空格(前一个数字的末尾空格和后一个数字的起始空格叠加),例如1  1会输出 ...1...1

前导空格的计算与元素间隔无关

前导空格公式(n-i-1)*2 仅用于整体居中对齐,与元素之间的间隔无关

例如:
当n=5,i=1(第二行):
前导空格数: (5-1-1)*2=6 ,即打印6个空格。
元素间隔:由%4d自动生成3个空格
6空格 +"…1…1”,即最终输出:  .........1...1(视觉上对齐为......1...1)。

五、

根据以下的代码判断:

int main()
{int* p = NULL;int arr[10] = {0};return 0;
}

A.p = arr     B.int (*ptr)[10] = &arr   C.p = &arr[0] 

 D.p = &arr 【错误】 -  p是int*类型的指针变量,而&arr对应的是一个数组指针int (*)[10]类型

例如我们前面学习的二维数组传参:

void test(int* arr)
{int i = 0;for(i = 0;i < 15; i++){printf("%d ",arr[i]);}
}
int main()
{int arr[3][5] = {{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};test(arr);//arr作为二维数组的数组名,表示的是首元素的地址,是第一行的地址,是一个一维数组的地址,类型是数组指针,而给函数传参时用一个整型指针来接收就不太恰当return 0;
}
//如果就是想要用整型指针来接收,那么应该将二维数组的首元素传进去:
test(&arr[0][0])

六、杨氏矩阵

题目内容:
有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在

以下的矩阵就是一个杨氏矩阵:

x为横坐标,y为纵坐标;这个数组的右上角和左下角(3和7)是特殊的,3是一列的最大数也是一行的最小数,而7与3反过来,以3为例:假如我们要查找的数字是7,此时3<7,去掉一行,此时右上角的数字变成了6,6<7,在去掉一行,此时9>7,去掉一列,8>7,再去掉一列,然后就查找到了7

void find_k(int arr[3][3],int r,int c,int k)
{int x = 0;int y = c - 1;int flag = 0;while(x<=r-1 && y>=0){if(arr[x][y] < k){x++;}else if(arr[x][y] > k){y++;}else{printf("找到了,下标是:(%d,%d)",x,y);flag = 1;break;}}if(flag == 0)printf("找不到\n");
}int main()
{int arr[3][3] = {1,2,3,4,5,6,7,8,9};int k = 0;printf("请输入要查找数:>");scanf("%d",&k);find_k(arr,3,3,k);return 0;
}

方法二:

void find_k(int arr[3][3],int* px,int* py,int k)
{int x = 0;int y = *py - 1;while(x<=*px-1 && y>=0){if(arr[x][y] < k){x++;}else if(arr[x][y] > k){y++;}else{*px = x;*py = y;return 1;}}return 0;
}int main()
{int arr[3][3] = {1,2,3,4,5,6,7,8,9};int k = 0;printf("请输入要查找数:>");scanf("%d",&k);int x = 3;int y = 3;int ret = find_k(arr,&x,&y,k);if(ret == 0)printf("找不到\n");elseprintf("找到了,下标是:(%d,%d)",x,y);return 0;
}

七、字符串左旋

题目内容:
实现一个函数,可以左旋字符串中的k个字符

例如:

ABCD左旋一个字符得到BCDA

ABCD左旋两个字符得到CDAB

思路:创建一个临时变量,每一次实现一个字符的交换

#include <stdio.h>
#include <string.h>
void left_move(int arr[],int k)
{int i = 0;int len = strlen(arr);k %= len;//旋转k位等价于k%len位,例如,字符串长度为5,旋转7位等价于旋转2位for(i = 0;i < k; i++){//旋转一个字符//1char tmp = arr[0];//2int j = 0;for(j = 0;j < len - 1; j++){arr[j] = arr[j+1];}//3arr[len-1] = tmp;}
}
int main()
{int arr[] = "abcdef";int k = 0;printf("左旋字符串的个数:>");scanf("%d",&k);left_move(arr,k);printf("%s\n",arr);return 0;
}

方法二:1 - 逆序前部分

               2 - 逆序后部分

               3 - 逆序整体

#include <stdio.h>
#include <string.h>
#include <assert.h>
void reverse(char* left,char* right)
{assert(left && right);while(left<right){char tmp = *left;*left = *right;*right = tmp;left++;right--;}
}
void left_move(char arr[],int k)
{int len = strlen(arr);k %= len;//逆序前部分reverse(arr,arr+k-1);//逆序后部分reverse(arr+k,arr+len-1);//整体逆序reverse(arr,arr+len-1);
}
int main()
{int arr[] = "abcdef";int k = 0;printf("左旋字符串个数:>");scanf("%d",&k);left_move(arr,k);printf("%s\n",arr);return 0;
}

八、字符串旋转结果

题目内容:
写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串,
例如:给定S1=AABCD和s2=BCDAA,返回1
        给定s1=abcd和S2=ACBD,返回0.
        AABCD左旋一个字符得到ABCDA
        AABCD左旋两个字符得到BCDAA
        AABCD右旋一个字符得到DAABC

左旋转:

#include <string.h>
void reverse(char* left, char* right)
{assert(left && right);while (left < right){char tmp = *left;*left = *right;*right = tmp;left++;right--;}
}
void left_move(char arr[],int k)
{int len = strlen(arr);k %= len;//逆序左reverse(arr, arr + k - 1);//逆序右reverse(arr + k, arr + len - 1);//逆序整体reverse(arr, arr + len - 1);
}
int is_left_move(int arr1[],int arr2[])
{int len1 = strlen(arr1);int len2 = strlen(arr2);if(len1 != len2)return 0;int i = 0;for(i = 0;i < len1; i++){left_move(arr1,1);if(strcmp(arr1,arr2) == 0)return 1;}return 0;
}
int main()
{char arr1[] = "AABCD";char arr2[] = "BCDAA";int ret = is_left_move(arr1,arr2);if(ret == 1)printf("YES\n");elseprintf("NO\n");return 0;
}

通过调试可观察其变化:

右旋转:

#include <string.h>
void reverse(char* left, char* right)
{assert(left && right);while (left < right){char tmp = *left;*left = *right;*right = tmp;left++;right--;}
}
void right_move(char arr[],int k)
{int len = strlen(arr);k %= len;//逆序左reverse(arr, arr+len-1-k);//逆序右reverse(arr+len-k,arr+len-1);//逆序整体reverse(arr, arr + len - 1);
}
int is_right_move(int arr1[],int arr3[])
{int len1 = strlen(arr1);int len3 = strlen(arr3);if(len1 != len3)return 0;int i = 0;for(i = 0;i < len1; i++){left_move(arr1,1);if(strcmp(arr1,arr3) == 0)return 1;}return 0;
}
int main()
{char arr1[] = "AABCD";char arr2[] = "DAABC";int ret = is_right_move(arr1,arr3);if(ret == 1)printf("YES\n");elseprintf("NO\n");return 0;
}

方法二:AABCD -> AABCDAABCD 给要与arr2比较的arr1再叠加整个字符串,看看arr2是否是arr1的子字符串
首先认识一下strcat、strncat、strstr(头文件都是 #include <string.h>)

strcat

int main()
{char arr[20] = "hello ";strcat(arr, "world");//在arr的基础上追加一个"world"字符串printf("%s\n", arr);//打印结果:hello worldreturn 0;
}

strncat - 可以设定要打印一个字符串中的几个字符

int main()
{char arr[20] = "hello ";strncat(arr, "world", 3);printf("%s\n", arr);//打印结果:hello worreturn 0;
}

strstr

int main()
{//是在arr1字符串中查找arr2是否存在//如果存在则返回arr2在arr1中的地址(位置);如果不存在返回NULLchar arr1[] = "abcdefabcdef";char arr2[] = "def";//如果arr1中有两个arr2,只返回第一个开始的地址char* ret = strstr(arr1, arr2);if (ret == NULL)printf("NO\n");elseprintf("%s\n",ret);//打印(%s)结果:defabcdef (从返回的地址开始向后打印)return 0;
}

左右旋转:

//右旋
int is_right_move(int arr1[],int arr3[])
{int len1 = strlen(arr1);int len3 = strlen(arr3);if(len1 != len3)return 0;strncat(arr1,arr1,len1);if(strstr(arr1,arr3) != NULL)return 1;elsereturn 0;
}
//左旋
int is_left_move(int arr1[],int arr2[])
{int len1 = strlen(arr1);int len2 = strlen(arr2);if(len1 != len2)return 0;strncat(arr1,arr1,len1);if(strstr(arr1,arr2) != NULL)return 1;elsereturn 0;
}
int main()
{char arr1[20] = "AABCD";char arr2[] = "BCDAA";char arr3[] = "DAABC";//int ret = is_left_move(arr1,arr2);int ret = is_right_move(arr1,arr3);if(ret == 1)printf("YES\n");elseprintf("NO\n");return 0;
}

九、

以下程序的输出结果是:1  6

int main()
{int aa[2][5] = { 10,9,8,7,6,5,4,3,2,1 };int* ptr1 = (int*)(&aa + 1);//&arr取出整个数组的地址,+1跳过了这个地址,然后强制转化为int*类型int* ptr2 = (int*)(*(aa + 1));//aa是二维数组数组名,即数组名为首行的地址(arr[0]),aa+1跳到第二行地址(arr[1]),然后解引用,强制转化为int*类型printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//*(ptr1-1) - 减1又回到了数组的最后一个元素的地址上,即1//*(ptr2-1) - 减1回到第一行最后一个元素的地址上,即6return 0;
}

相关文章:

  • 轻量化高精度的视频语义分割
  • std::unordered_set(C++)
  • 黑马点评:附近商铺+用户签到+UV统计【学习笔记】
  • Spring Boot资源耗尽问题排查与优化
  • Agent的九种设计模式 介绍
  • 基于PySide6与pyCATIA的圆柱体特征生成工具开发实战——NX建模之圆柱命令的参考与移植
  • 在 Babylon.js 中实现智能异步资源加载队列管理
  • React 事件处理基础
  • eNSP无法启动AR报错码40,而且按照eNSP帮助手册排查都没用,我的处理方法【自己存档版】
  • 关于使用webpack构建的vue项目,如何使用windicss
  • 移植的LVGL显示三分之二白屏三分之一灰屏 [正点原子探索者]
  • 53、对 $nextTick异步渲染的理解
  • Selenium 选择器定位元素方式详解
  • AI Agents系列之AI代理架构体系
  • ubuntu 22.04 使用ssh-keygen创建ssh互信账户
  • 基于Atlas 800I A2 + Ubuntu 22.04 LTS 离线部署神州鲲泰问学一体机平台
  • Axure PR 9 中继器 10 编辑行
  • HTTP 核心概念
  • Evidential Deep Learning和证据理论教材的区别(主要是概念)
  • 写论文时降AIGC和降重的一些注意事项
  • 广西一季度GDP为6833.92亿元,同比增长5.8%
  • 受贿超8.22亿元,新疆维吾尔自治区党委原副书记李鹏新一审被判死缓
  • 日方炒作中国社会治安形势不佳,外交部:政治操弄意图明显
  • 商务部:支持“来数加工”等新业态新模式,发展游戏出海业务
  • 中国旅游日主题月期间,东航将准备超51.9万套特惠机票
  • “我们一直都是面向全世界做生意”,“世界超市”义乌一线走访见闻