阶段习题详解
字符串逆序
写一个函数,可以逆序一个字符串的内容。
#include <string.h>
#include <assert.h>
void reverse(char *str) {
assert(str);
int len = strlen(str);
char *left = str;
char *right = str + len - 1;
while (left < right) {
char tmp = *left;
*left = *right;
*right = tmp;
left++;
right--;
}
}
int main() {
char arr[200] = {0};
scanf("%s", arr);
reverse(arr);
printf("%s", arr);
}
计算求和
求sum = a +aa+aaa+…的前n项的和,其中的a只是一个数字。
int main() {
int a = 0;
int n = 0;
scanf("%d%d", &a, &n);
int sum = 0;
int i = 0;
int res = 0;
for (i = 0; i < n; ++i) {
res = res * 10 + a;
sum += res;
}
printf("%d\n", sum);
return 0;
}
打印水仙花数
求出0~100000之间的所有水仙花数并输出。 “水仙花数”是指一个n位数,其各位数字的n次方之和恰好等于该数本身,如153 = 13+53+33,则153是一个水仙花数。
int main(){
for (int i = 0; i < 100000; i++) {
int n = 1;
int tmp = i;
while (tmp/=10){
n++;
}
tmp = i;
int sum = 0;
while (tmp){
sum+=pow(tmp%10,n);
tmp/=10;
}
if(i == sum){
printf("%d ",i);
}
}
return 0;
}
打印菱形
用c语言在屏幕上打印以下的图案。
int main(){
int line = 7;
for (int i = 0; i < line; ++i) {
for (int j = 0; j < line-1-i; ++j) {
printf(" ");
}
for (int j = 0; j < 2 * i + 1; ++j) {
printf("*");
}
printf("\n");
}
for (int i = 0; i < line - 1; ++i) {
for (int j = 0; j < i+1; ++j) {
printf(" ");
}
for (int j = 0; j < 2*(line-i-1)-1; ++j) {
printf("*");
}
printf("\n");
}
return 0;
}
解析:这个题中的每次for循环的起始值为1或者0的时候,后面的条件判断也会有很大的变化。
喝汽水
喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以得多少汽水。
int main() {
int num = 20;
int sum = 0;
int bottle = 0;
sum = num;
bottle = num;
while (bottle >= 2) {
num = bottle / 2;
if (bottle % 2 == 1) {
bottle = 1;
} else {
bottle = 0;
}
sum += num;
bottle += num;
num = 0;
}
printf("%d", sum);
return 0;
}
解析:将当前有的可乐数,当前空瓶数,已经有过的可乐数按照实际情况走一遍流程然后思考终止条件。
调整奇偶数顺序
调整数组使奇数全部位于偶数的前面。
输入一个整形数组,实现一个函数, 来调整该数组中数字的顺序使得数组中所有的技术位于数组的前半部分,所有的偶数位于数组的后半部分。
void move(int *arr, int sz) {
int *left = arr;
int *right = arr + sz - 1;
while (1) {
while (*left % 2 == 1) {
left++;
}
while (*right % 2 == 0) {
right--;
}
if (left < right) {
int tmp = *right;
*right = *left;
*left = tmp;
} else break;
}
}
void print(int *arr, int size) {
for (int i = 0; i < size; ++i) {
printf("%d ", arr[i]);
}
}
int main() {
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int sz = sizeof(arr) / sizeof(arr[0]);
move(arr, sz);
print(arr, sz);
return 0;
}
解析:整体的思路就是从左边开始找奇数从右端开始找偶数,找到就交换。这样就可以将偶数放在后面,奇数放在前面了
杨辉三角
在屏幕上打印杨辉三角
int main() {
int arr[10][10] = {0};
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
if (j == 0) {
arr[i][j] = 1;
}
if (i == j) {
arr[i][j] = 1;
}
if ((i > 0) && (j > 0)) {
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
}
}
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10-1-i; ++j) {
printf(" ");
}
for (int j = 0; j < 10; ++j) {
(j > i) ? printf(" ") : printf("%3d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
解析:第一步,想到应该使用什么来存放数据(数组),左边的空白就是最后打印的时候输出相应大小的空格长度即可。找出数之间的规律,先初始化,无法计算的数据,然后计算可以计算的数据并填入数组。最后进行打印即可。
猜凶手
日本某地发生异常谋杀案,警察通过排查确定杀人凶手四个嫌疑犯的一个。已知三人说了真话,1人说了假话。 以下是供词:A说:不是我。B说:是C。C说:是D。D说:C在胡说。 现在根据这些信息,写一个程序来确定谁是凶手。
int main(){
int killer = 0;
for(killer = 'a';killer<='d';killer++){
if((killer=='a')+(killer=='c')+(killer=='d')+(killer!='d')==3){
printf("killer is %c",killer);
}
}
return 0;
}
解析:将4个人说的话转化为逻辑判断语句。假设凶手是谁,然后判断此时四条语句的正确数。如果是3,那就说明我们要的答案是当前的条件上表示的谁是凶手。
猜名次
5位运动员参加了10米跳水比赛,有人让他们预测比赛结果:A选手说:B第二,我第三。B选手说:我第二,E第四。C选手说:我第一,D第二。D选手说:C最后,我第三。E选手说:我第四,A第一。比赛结束后每位选手都说对了一半,请编程确定比赛的名次。
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) &&
(a * b * c * d * e == 120))
printf("a=%d,b=%d,c=%d,d=%d,e=%d", a, b, c, d, e);
}
}
}
}
}
return 0;
}
解析:这个思路就相当于枚举,将所有的情况列举出来,筛选出满足条件的。
字符串左旋
实现一个函数,可以左旋转k个字符。
例如: ABCD左旋转一个字符,BCDA ABCD左旋转两个字符,CDAB
#include <string.h>
void left_move(char *arr,int k){
int len = strlen(arr);
for (int i = 0; i < k; ++i) {
char tmp = *arr;
for (int j = 0; j < len-1; ++j) {
*(arr+j) = *(arr+j+1);
}
*(arr+len-1) = tmp;
}
}
int main(){
char arr[] = "abcdef";
int k = 2;
left_move(arr,k);
printf("%s",arr);
return 0;
}
解析:这是暴力求解法。每一次向左移动一个字符。执行n次。 如果是右旋转,我们可以先将最右边的值放在临时变量中然后向右移动。
#include <string.h>
void reverse(char* start, char *end) {
while (start<end){
char tmp = *start;
*start = *end;
*end = tmp;
start++;
end--;
}
}
void left_move(char *arr, int k) {
int len = strlen(arr);
k = k % len;
reverse(arr, arr + k - 1);
reverse(arr + k, arr + len - 1);
reverse(arr, arr + len - 1);
}
解析:将字符串进行三次翻转。因为旋转后的字符串在小范围内都是存在一定顺序的,然后,对于一段字符而言,经过两次就可以恢复顺序,所以有了总共翻转三次的思想。
字符串旋转结果
写一个函数,判断一个字符串中是否为另一个字符串旋转后的字符串。 例如:给定s1=AABCD和s2=BCDAA,返回1
给定s1 = abcd 和 s2 = acbd,返回0。
#include <string.h>
void reverse(char *start, char *end) {
while (start < end) {
char tmp = *start;
*start = *end;
*end = tmp;
start++;
end--;
}
}
void left_move(char *arr, int k) {
int len = strlen(arr);
k = k % len;
reverse(arr, arr + k - 1);
reverse(arr + k, arr + len - 1);
reverse(arr, arr + len - 1);
}
int is_move(char *s1, const char *s2) {
int len = strlen(s1);
for (int i = 0; i < len - 1; ++i) {
left_move(s1, 1);
int res = strcmp(s1, s2);
if (res == 1) {
return 1;
}
}
return 0;
}
int main() {
char arr1[] = "abcdef";
char arr2[] = "cdefab";
int res = is_move(arr1, arr2);
if (res == 1) {
printf("%s是%s旋转后的字符串。", arr2, arr1);
} else printf("%s不是%s旋转后的字符串。", arr2, arr1);
}
解析:这题的主要功能是实现is_move函数,剩下的功能都和上一题字符串左旋相同。这个解法也是相当于将所有的旋转后的情况拿出来和给定字符串进行对比。其实还有其他的方法。
int is_move(char *s1, char *s2) {
int len1 = strlen(s1);
int len2 = strlen(s2);
if(len1!=len2) return 0;
strncat(s1,s1, len1);
char * res = strstr(s1,s2);
if(res == NULL)return 0;
else return 1;
}
int main() {
char arr1[30] = "abcdef";
char arr2[] = "cdefacb";
int res = is_move(arr1, arr2);
if (res == 1) {
printf("%s是%s旋转后的字符串。", arr2, arr1);
} else printf("%s不是%s旋转后的字符串。", arr2, arr1);
}
解析:在原字符串的最后追加一个自己。然后,在新生成的字符串中寻找另一个字符串是否为新生成的子串。
杨氏矩阵
有一个数字数组,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。
要求:时间复杂度是小于O(n)。
提示:一行中的最大值,或者一列中的最大值可以直接排除一行或者一列。当然最小值也是可以的。那我我们为了一下子可以排除掉一行我们可以取左下角或者右上角,因为这两个位置,同时具有一个最大值和一个最小值的特性。
int FindNum(int arr[4][4], int k, int row, int col) {
int x = 0;
int y = col - 1;
while ((x >= 0 && x < row) && (y >= 0 && y < col)) {
if (arr[x][y] == k) return 1;
else if (arr[x][y] > k) y--;
else if (arr[x][y] < k) x++;
}
return 0;
}
int main() {
int arr[4][4] = {{1, 2, 3, 4},
{4, 5, 6, 7},
{7, 8, 9, 10},
{8, 9, 12, 13}};
int k = 8;
int row = sizeof(arr) / sizeof(arr[0]);
int col = sizeof(arr[0]) / sizeof(arr[0][0]);
int res = FindNum(arr, k, row, col);
if (res == 1)printf("找到了\n");
else printf("没有找到\n");
return 0;
}
注:如果要在函数外部进行访问下标的时候,可以将x、y定义在函数之外,将其指针传进函数,然后在外部访问输出。(这就是基本功的练习了。)
|