文章目录
- [C语言五天速成 Day2:20道经典算法](#C语言五天速成 Day2:20道经典算法)
-
- 题21:进制转换(十进制转二进制)
- 题22:进制转换(二进制转十进制)
- 题23:递归求最大公约数
- 题24:非递归求阶乘
- 题25:统计一个数的因子个数
- 题26:字符串拼接(不使用strcat)
- 题27:选择排序(升序)
- 题28:打印杨辉三角(前n行)
- 题29:判断一个数是否为水仙花数
- 题30:数组元素平移(右移k位)
- 题31:统计字符串中数字出现次数
- 题32:递归实现字符串反转
- 题33:求两个数组的交集(元素可重复)
- 题34:打印倒直角三角形(星号)
- 题35:计算一个数的二进制中1的个数
- 题36:字符串比较(不使用strcmp)
- 题37:求数组的前缀和数组
- 题38:递归实现斐波那契数列(带记忆化)
- 题39:打印正六边形(星号)
- 题40:删除字符串中指定字符
C语言五天速成 Day2:20道经典算法
题21:进制转换(十进制转二进制)
题目描述
输入一个非负整数n(0≤n≤1000),将其转换为二进制数并输出。要求手动实现转换逻辑,不使用库函数,处理n=0的特殊情况。
C语言实现
c
#include <stdio.h>
void decimalToBinary(int n) {
if (n == 0) {
printf("0"); // 特殊情况:0的二进制为0
return;
}
int stack[32], top = -1; // 用栈存储二进制位(逆序输出)
while (n > 0) {
stack[++top] = n % 2;
n = n / 2;
}
// 出栈输出(正序)
while (top >= 0) {
printf("%d", stack[top--]);
}
}
int main() {
int n;
printf("请输入非负整数n:");
scanf("%d", &n);
if (n < 0 || n > 1000) {
printf("输入无效,n需在0~1000之间\n");
return 1;
}
printf("对应的二进制数:");
decimalToBinary(n);
printf("\n");
return 0;
}
题22:进制转换(二进制转十进制)
题目描述
输入一个二进制字符串(长度≤10,仅含0和1),将其转换为十进制整数并输出。注意处理前导零的情况(如"00101"转换为5)。
C语言实现
c
#include <stdio.h>
#include <string.h>
#include <math.h>
int binaryToDecimal(char binary[]) {
int len = strlen(binary);
int decimal = 0;
for (int i = 0; i < len; i++) {
// 从左到右,每一位乘以2的对应次方
decimal += (binary[i] - '0') * pow(2, len - 1 - i);
}
return decimal;
}
int main() {
char binary[11];
printf("请输入二进制字符串(仅含0和1):");
scanf("%s", binary);
// 验证输入是否为合法二进制
for (int i = 0; i < strlen(binary); i++) {
if (binary[i] != '0' && binary[i] != '1') {
printf("输入无效,需为二进制字符串\n");
return 1;
}
}
int decimal = binaryToDecimal(binary);
printf("对应的十进制数:%d\n", decimal);
return 0;
}
题23:递归求最大公约数
题目描述
输入两个正整数a、b(1≤a,b≤10⁶),使用递归算法实现辗转相除法,计算它们的最大公约数(GCD)并输出。
C语言实现
c
#include <stdio.h>
// 递归版辗转相除法求GCD
long long gcdRecursive(long long a, long long b) {
if (b == 0) {
return a; // 递归终止条件
}
return gcdRecursive(b, a % b);
}
int main() {
long long a, b;
printf("请输入两个正整数:");
scanf("%lld %lld", &a, &b);
if (a < 1 || b < 1) {
printf("输入无效,请输入正整数\n");
return 1;
}
printf("最大公约数(GCD):%lld\n", gcdRecursive(a, b));
return 0;
}
题24:非递归求阶乘
题目描述
输入一个正整数n(1≤n≤20),使用循环(非递归)算法计算n的阶乘,使用long long类型存储结果,避免数据溢出。
C语言实现
c
#include <stdio.h>
long long factorialNonRecursive(int n) {
long long result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
int main() {
int n;
printf("请输入正整数n:");
scanf("%d", &n);
if (n < 1 || n > 20) {
printf("输入无效,n需在1~20之间\n");
return 1;
}
long long res = factorialNonRecursive(n);
printf("%d的阶乘:%lld\n", n, res);
return 0;
}
题25:统计一个数的因子个数
题目描述
输入一个正整数n(1≤n≤10⁵),统计该数的所有正因子的个数(包括1和自身),优化算法减少循环次数。
C语言实现
c
#include <stdio.h>
#include <math.h>
int countFactors(int n) {
if (n == 1) {
return 1; // 1的因子只有自身
}
int count = 0;
// 遍历到sqrt(n),成对统计因子
for (int i = 1; i <= sqrt(n); i++) {
if (n % i == 0) {
if (i == n / i) {
count++; // 因子相等,只算一个
} else {
count += 2; // 因子不相等,算两个
}
}
}
return count;
}
int main() {
int n;
printf("请输入正整数n:");
scanf("%d", &n);
if (n < 1 || n > 1e5) {
printf("输入无效,n需在1~100000之间\n");
return 1;
}
int num = countFactors(n);
printf("%d的正因子个数:%d\n", n, num);
return 0;
}
题26:字符串拼接(不使用strcat)
题目描述
输入两个字符串s1和s2(长度均≤50),手动实现字符串拼接功能(将s2拼接到s1末尾),不使用库函数strcat,输出拼接后的字符串。
C语言实现
c
#include <stdio.h>
#include <string.h>
void myStrcat(char s1[], char s2[]) {
int len1 = strlen(s1);
int len2 = strlen(s2);
// 将s2的字符逐个复制到s1末尾
for (int i = 0; i <= len2; i++) { // 包含'\0'
s1[len1 + i] = s2[i];
}
}
int main() {
char s1[101], s2[51]; // s1预留足够空间
printf("请输入第一个字符串:");
scanf("%s", s1);
printf("请输入第二个字符串:");
scanf("%s", s2);
if (strlen(s1) + strlen(s2) > 100) {
printf("字符串过长,拼接后会溢出\n");
return 1;
}
myStrcat(s1, s2);
printf("拼接后的字符串:%s\n", s1);
return 0;
}
题27:选择排序(升序)
题目描述
输入一个长度为n(1≤n≤100)的整数数组,使用选择排序算法将数组按升序排列后输出。选择排序逻辑:每次选最小元素放到已排序部分末尾。
C语言实现
c
#include <stdio.h>
void selectionSort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
int minIndex = i; // 记录最小元素下标
// 寻找未排序部分的最小元素
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换最小元素与当前位置元素
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
int main() {
int n;
printf("请输入数组长度:");
scanf("%d", &n);
if (n < 1 || n > 100) {
printf("输入无效,长度需在1~100之间\n");
return 1;
}
int arr[100];
printf("请输入数组元素:");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
selectionSort(arr, n);
printf("升序排列后的数组:");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
题28:打印杨辉三角(前n行)
题目描述
输入一个正整数n(1≤n≤10),打印杨辉三角的前n行。杨辉三角特点:每行首尾元素为1,其余元素为上一行相邻两元素之和。
C语言实现
c
#include <stdio.h>
int main() {
int n;
printf("请输入杨辉三角行数n:");
scanf("%d", &n);
if (n < 1 || n > 10) {
printf("输入无效,行数需在1~10之间\n");
return 1;
}
int yanghui[10][10] = {0};
// 初始化杨辉三角
for (int i = 0; i < n; i++) {
yanghui[i][0] = 1; // 每行首元素为1
yanghui[i][i] = 1; // 每行尾元素为1
// 计算中间元素
for (int j = 1; j < i; j++) {
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
}
}
// 打印杨辉三角
for (int i = 0; i < n; i++) {
// 打印空格,使三角居中
for (int j = 0; j < n - i - 1; j++) {
printf(" ");
}
for (int j = 0; j <= i; j++) {
printf("%d ", yanghui[i][j]);
}
printf("\n");
}
return 0;
}
题29:判断一个数是否为水仙花数
题目描述
输入一个三位数n(100≤n≤999),判断该数是否为水仙花数。水仙花数定义:一个三位数,其各位数字的立方和等于该数本身(如153=1³+5³+3³)。
C语言实现
c
#include <stdio.h>
int isNarcissisticNumber(int n) {
int hundreds = n / 100; // 百位
int tens = (n / 10) % 10; // 十位
int units = n % 10; // 个位
int sum = hundreds*hundreds*hundreds + tens*tens*tens + units*units*units;
return sum == n;
}
int main() {
int n;
printf("请输入一个三位数:");
scanf("%d", &n);
if (n < 100 || n > 999) {
printf("输入无效,需为三位数\n");
return 1;
}
if (isNarcissisticNumber(n)) {
printf("%d是水仙花数\n", n);
} else {
printf("%d不是水仙花数\n", n);
}
return 0;
}
题30:数组元素平移(右移k位)
题目描述
输入一个长度为n(1≤n≤100)的整数数组和一个整数k(1≤k≤n),将数组元素向右平移k位(循环右移),输出平移后的数组。例如:数组[1,2,3,4,5]右移2位后为[4,5,1,2,3]。
C语言实现
c
#include <stdio.h>
// 反转数组指定区间[left, right]
void reverse(int arr[], int left, int right) {
while (left < right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
// 循环右移k位
void rightShift(int arr[], int n, int k) {
k = k % n; // 处理k>n的情况
reverse(arr, 0, n - 1); // 反转整个数组
reverse(arr, 0, k - 1); // 反转前k位
reverse(arr, k, n - 1); // 反转剩余部分
}
int main() {
int n, k;
printf("请输入数组长度和右移位数:");
scanf("%d %d", &n, &k);
if (n < 1 || n > 100 || k < 1) {
printf("输入无效,长度需1~100,移位数≥1\n");
return 1;
}
int arr[100];
printf("请输入数组元素:");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
rightShift(arr, n, k);
printf("右移%d位后的数组:", k);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
题31:统计字符串中数字出现次数
题目描述
输入一个字符串(长度≤100,含字母、数字、空格、标点),统计字符串中0-9每个数字出现的次数,忽略非数字字符,按数字顺序输出结果。
C语言实现
c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char str[101];
int count[10] = {0}; // 存储0-9的出现次数
printf("请输入字符串:");
getchar();
fgets(str, 101, stdin);
str[strcspn(str, "\n")] = '\0';
for (int i = 0; i < strlen(str); i++) {
if (isdigit(str[i])) { // 判断是否为数字
count[str[i] - '0']++;
}
}
printf("数字出现次数统计:\n");
for (int i = 0; i < 10; i++) {
if (count[i] > 0) {
printf("数字%d:%d次\n", i, count[i]);
}
}
return 0;
}
题32:递归实现字符串反转
题目描述
输入一个字符串(长度≤100,不含空格),使用递归算法实现字符串反转,输出反转后的字符串。
C语言实现
c
#include <stdio.h>
#include <string.h>
void reverseStringRecursive(char str[], int left, int right) {
if (left >= right) {
return; // 递归终止条件
}
// 交换左右字符
char temp = str[left];
str[left] = str[right];
str[right] = temp;
// 递归处理剩余部分
reverseStringRecursive(str, left + 1, right - 1);
}
int main() {
char str[101];
printf("请输入字符串(不含空格):");
scanf("%s", str);
int len = strlen(str);
reverseStringRecursive(str, 0, len - 1);
printf("反转后的字符串:%s\n", str);
return 0;
}
题33:求两个数组的交集(元素可重复)
题目描述
输入两个整数数组arr1和arr2(长度均≤50),求两个数组的交集(元素可重复,顺序与arr1一致),输出交集数组。例如:arr1=[1,2,2,1],arr2=[2,2],交集为[2,2]。
C语言实现
c
#include <stdio.h>
#define MAX_LEN 50
// 标记元素是否已被使用
void markUsed(int arr[], int len, int target, int used[]) {
for (int i = 0; i < len; i++) {
if (arr[i] == target && used[i] == 0) {
used[i] = 1;
break;
}
}
}
// 求交集
int getIntersection(int arr1[], int len1, int arr2[], int len2, int intersection[]) {
int used[MAX_LEN] = {0}; // 标记arr2中元素是否已使用
int idx = 0;
for (int i = 0; i < len1; i++) {
for (int j = 0; j < len2; j++) {
if (arr1[i] == arr2[j] && used[j] == 0) {
intersection[idx++] = arr1[i];
markUsed(arr2, len2, arr1[i], used);
break;
}
}
}
return idx; // 交集数组长度
}
int main() {
int len1, len2, intersection[MAX_LEN];
int arr1[MAX_LEN], arr2[MAX_LEN];
printf("请输入arr1长度和元素:");
scanf("%d", &len1);
for (int i = 0; i < len1; i++) {
scanf("%d", &arr1[i]);
}
printf("请输入arr2长度和元素:");
scanf("%d", &len2);
for (int i = 0; i < len2; i++) {
scanf("%d", &arr2[i]);
}
int interLen = getIntersection(arr1, len1, arr2, len2, intersection);
printf("两个数组的交集:");
for (int i = 0; i < interLen; i++) {
printf("%d ", intersection[i]);
}
printf("\n");
return 0;
}
题34:打印倒直角三角形(星号)
题目描述
输入一个正整数n(1≤n≤10),打印一个直角边长度为n的倒直角三角形(直角在左上角),由星号组成。例如n=3时,图案如下:
**
C语言实现
c
#include <stdio.h>
int main() {
int n;
printf("请输入倒直角三角形直角边长度n:");
scanf("%d", &n);
if (n < 1 || n > 10) {
printf("输入无效,长度需在1~10之间\n");
return 1;
}
// 行数从n递减到1,每行星号数等于行数
for (int i = n; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
printf("*");
}
printf("\n");
}
return 0;
}
题35:计算一个数的二进制中1的个数
题目描述
输入一个非负整数n(0≤n≤1000),计算该数的二进制表示中1的个数并输出。使用位运算优化算法。
C语言实现
c
#include <stdio.h>
int countOneInBinary(int n) {
int count = 0;
while (n > 0) {
n &= n - 1; // 清除最低位的1
count++;
}
return count;
}
int main() {
int n;
printf("请输入非负整数n:");
scanf("%d", &n);
if (n < 0 || n > 1000) {
printf("输入无效,n需在0~1000之间\n");
return 1;
}
int num = countOneInBinary(n);
printf("%d的二进制中1的个数:%d\n", n, num);
return 0;
}
题36:字符串比较(不使用strcmp)
题目描述
输入两个字符串s1和s2(长度均≤50),手动实现字符串比较功能(不使用strcmp),按ASCII码值比较:s1>s2返回1,s1=s2返回0,s1<s2返回-1,输出结果。
C语言实现
c
#include <stdio.h>
#include <string.h>
int myStrcmp(char s1[], char s2[]) {
int i = 0;
// 逐字符比较,直到遇到'\0'或不同字符
while (s1[i] != '\0' && s2[i] != '\0' && s1[i] == s2[i]) {
i++;
}
// 返回ASCII码差值
if (s1[i] > s2[i]) {
return 1;
} else if (s1[i] < s2[i]) {
return -1;
} else {
return 0;
}
}
int main() {
char s1[51], s2[51];
printf("请输入第一个字符串:");
scanf("%s", s1);
printf("请输入第二个字符串:");
scanf("%s", s2);
int res = myStrcmp(s1, s2);
if (res == 1) {
printf("s1 > s2\n");
} else if (res == 0) {
printf("s1 == s2\n");
} else {
printf("s1 < s2\n");
}
return 0;
}
题37:求数组的前缀和数组
题目描述
输入一个长度为n(1≤n≤100)的整数数组,计算其前缀和数组并输出。前缀和数组定义:prefix[i] = arr[0] + arr[1] + ... + arr[i]。
C语言实现
c
#include <stdio.h>
void getPrefixSum(int arr[], int n, int prefix[]) {
prefix[0] = arr[0];
for (int i = 1; i < n; i++) {
prefix[i] = prefix[i-1] + arr[i];
}
}
int main() {
int n;
printf("请输入数组长度:");
scanf("%d", &n);
if (n < 1 || n > 100) {
printf("输入无效,长度需在1~100之间\n");
return 1;
}
int arr[100], prefix[100];
printf("请输入数组元素:");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
getPrefixSum(arr, n, prefix);
printf("前缀和数组:");
for (int i = 0; i < n; i++) {
printf("%d ", prefix[i]);
}
printf("\n");
return 0;
}
题38:递归实现斐波那契数列(带记忆化)
题目描述
输入一个正整数n(1≤n≤100),使用递归算法实现斐波那契数列,加入记忆化优化(避免重复计算),输出第n项。
C语言实现
c
#include <stdio.h>
long long memo[101] = {0}; // 记忆化数组,存储已计算的项
long long fibMemo(int n) {
if (n <= 2) {
return 1;
}
if (memo[n] != 0) {
return memo[n]; // 已计算,直接返回
}
memo[n] = fibMemo(n-1) + fibMemo(n-2); // 计算并存储
return memo[n];
}
int main() {
int n;
printf("请输入正整数n:");
scanf("%d", &n);
if (n < 1 || n > 100) {
printf("输入无效,n需在1~100之间\n");
return 1;
}
long long res = fibMemo(n);
printf("斐波那契数列第%d项:%lld\n", n, res);
return 0;
}
题39:打印正六边形(星号)
题目描述
输入一个正整数n(2≤n≤5),打印一个边长为n的正六边形,由星号组成。例如n=2时,图案如下:
**
**
C语言实现
c
#include <stdio.h>
int main() {
int n;
printf("请输入正六边形边长n:");
scanf("%d", &n);
if (n < 2 || n > 5) {
printf("输入无效,边长需在2~5之间\n");
return 1;
}
int half = n - 1;
// 上半部分(包括中间行)
for (int i = 0; i < n; i++) {
// 打印空格
for (int j = 0; j < half - i; j++) {
printf(" ");
}
// 打印星号
for (int j = 0; j < n + 2 * i; j++) {
printf("*");
}
printf("\n");
}
// 下半部分
for (int i = n - 2; i >= 0; i--) {
// 打印空格
for (int j = 0; j < half - i; j++) {
printf(" ");
}
// 打印星号
for (int j = 0; j < n + 2 * i; j++) {
printf("*");
}
printf("\n");
}
return 0;
}
题40:删除字符串中指定字符
题目描述
输入一个字符串(长度≤100)和一个指定字符c,删除字符串中所有的c字符,输出删除后的字符串。要求原地修改,不使用额外字符串空间。
C语言实现
c
#include <stdio.h>
#include <string.h>
void deleteChar(char str[], char c) {
int idx = 0; // 记录有效字符下标
for (int i = 0; i < strlen(str); i++) {
if (str[i] != c) {
str[idx++] = str[i];
}
}
str[idx] = '\0'; // 加上字符串结束符
}
int main() {
char str[101], c;
printf("请输入字符串:");
scanf("%s", str);
printf("请输入要删除的字符:");
scanf(" %c", &c); // 空格吸收换行
deleteChar(str, c);
printf("删除后的字符串:%s\n", str);
return 0;
}