> 文章列表 > 【C语言练习题】

【C语言练习题】

【C语言练习题】

喝汽水
【C语言练习题】

20元->20空瓶
20空瓶->送10瓶
10瓶->送5瓶
5瓶-> 送2瓶+1瓶(存在)
3瓶->送1瓶+1瓶(存在)
2瓶->1瓶
总共喝了20+19瓶
总共喝了的数量分为两部分

  1. 实实在在买的
  2. 用空瓶子换的
int main()
{int money;int total;int empty;scanf("%d", &money);//直接买的total = money;empty = total;//送的while (empty > 1){total += empty / 2;empty = empty / 2 + empty % 2;}printf("%d\\n", total);return 0;
}

调整奇数偶数顺序
【C语言练习题】

奇数在数组中前半部分,偶数在数组中后半部分,可以通过双指针来解决
【C语言练习题】
left指向首元素,right指向尾元素,当left指向的元素不是偶数,left向后挪动直到指向偶数,right指向的元素不是奇数,right向前挪动直到right指向奇数
交换left和right指向的元素,重复上述动作直到left>=right

void Move(int* arr, int sz)
{int left = 0;int right = sz - 1;while (left < right){//让left指向偶数while (arr[left] % 2 == 1 && left < right) left++;//循环条件保证数组不会因为全是奇数而越界//让right指向奇数while (arr[right] % 2 == 0 && left < right) right--;//循环条件保证数组不会因为全是奇数而越界//交换int tmp = arr[left];arr[left] = arr[right];arr[right] = tmp;}
}
int main()
{int arr[] = { 1, 2, 3, 4, 5, 6, 7 ,8 };int sz = sizeof arr / sizeof arr[0];Move(arr, sz);for (int i = 0; i < sz; i++)printf("%d ", arr[i]);return 0;
}

猜名次
【C语言练习题】

每个人都可能有5种状态,第一、第二、第三、第四、第五
每位选手说对了一半可以用条件表达式x+y==1(x、y表示事件)来表示

int main()
{int a, b, c, d, e;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++){//保证a五人排名不重复if (a * b * c * d * e == 120){//5个人都说对一半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;}}}}}}}return 0;
}

猜凶手
【C语言练习题】

从凶手的状态考虑有4种,凶手是a,凶手是b,凶手是c,凶手是d,三个人说真话可以表示为p+q+x+y==3

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

从4个人的状态考虑每个人都有是凶手和不是凶手两种状态,因此还可以这么写

int main()
{char a, b, c, d;for (a = 0; a <= 1; a++){for (b = 0; b <= 1; b++){for (c = 0; c <= 1; c++){for (d = 0; d <= 1; d++){if ((a != 1) + (c == 1) + (d == 1) + (d != 1) == 3){printf("%d %d %d %d", a, b, c, d);//1为凶手goto lip;}}}}}
lip:;
}

字符串左旋
【C语言练习题】

可以暴力遍历,循环k次,每次把最左边的字符移动到最右边,比较简单,这里不再赘述
想要左旋转字符串,可以通过以下三步完成

  1. 逆序前k个字符
  2. 逆序后len-k个字符
  3. 逆序整个字符串(不包括结束符)
#include <string.h>
void Reverse(char* start, char* end)
{int left = 0;int right = end - start;while (left < right){char tmp = start[left];start[left] = start[right];start[right] = tmp;left++;right--;}
}
char* LeftMoveStr(char* str, int k)
{k %= strlen(str);Reverse(str, str + k - 1);Reverse(str + k, str + strlen(str) - 1);Reverse(str, str + strlen(str) - 1);return str;
}
int main()
{char str[] = "abcdefgh";int k;scanf("%d", &k);printf("%s\\n", LeftMoveStr(str, k));return 0;
}

字符串旋转结果
【C语言练习题】

本题当然可以将所有旋转后的结果放到一个数组里,然后进行查找,但是这种做法既不好操作,也太费事,但是这题有一个很简单的做法:
其实ABCDE无论怎么旋,旋转后的所有结果,都包含在了ABCDEABCD这个字符串里了。
所以做法很简单,只需要将原字符串再来一遍接在后面,然后找一找待查找的字符串是不是两倍原字符串的子集即可。

int IsLeftRotate(char* str, char* find)
{strncat(str, str, strlen(str));//注意这里不要使用strcat拼接自己return strstr(str, find) == NULL ? 0 : 1;
}
int main()
{char str1[20] = "abcdef";char find[8] = "cdefab";if (IsLeftRotate(str1, find)){printf("Yes\\n");}else printf("No\\n");return 0;
}

杨氏矩阵
【C语言练习题】

我们仔细分析,不难发现,对于杨氏矩阵老说,右上角和左下角的元素是有特点的。右上角的元素是一行中最大的,一列中最小的。左下角的元素是一行中最小的,是一列中最大的。所以我们可以从右上角或者左下角开始查找。比如:从右上角开始查找的时候,右上角的元素比我们要查找元素小,我们就可以去掉右上角元素所在的这一行;右上角的元素比我们要查找的元素大,我们就可以去掉右上角元素所在的这一列。然后依然找右上角的元素继续和要查找的元素与比较。这样每一次比较去掉一行或者去掉一列。这个查找效率是高于遍历数组元素的,所以时间复杂度是小于O(N),也满足题目要求。

int FindKeyFromArr(int arr[][3], int* row, int* col, int key)
{int x = 0;int y = *col - 1;//循环终止条件while (x <= row - 1 && y >= 0){if (arr[x][y] < key) x++;else if (arr[x][y] > key) y--;else{//返回找到的坐标*row = x + 1;*col = y + 1;return 1;}}return 0;
}
int main()
{int arr[3][3] = { {1,2,3}, {4,5,6}, {7, 8, 9} };int key;int x = 3; int y = 3;scanf("%d", &key);int ret = FindKeyFromArr(arr, &x, &y, key);if (1 == ret){printf("找到啦!下标为(%d,%d)\\n", x, y);}else printf("没找到!\\n");return 0;
}