Day3:20道核心题型(C语言实现)
题41:求两个数组的并集(去重)
题目描述
输入两个整数数组arr1和arr2(长度均≤50),求两个数组的并集(去除重复元素,顺序无要求),输出并集数组及长度。
C语言实现
c
#include <stdio.h>
#define MAX_LEN 100
// 判断元素是否在数组中
int isInArray(int arr[], int len, int num) {
for (int i = 0; i < len; i++) {
if (arr[i] == num) {
return 1;
}
}
return 0;
}
// 求并集(去重)
int getUnion(int arr1[], int len1, int arr2[], int len2, int unionArr[]) {
int idx = 0;
// 加入arr1的元素(去重)
for (int i = 0; i < len1; i++) {
if (!isInArray(unionArr, idx, arr1[i])) {
unionArr[idx++] = arr1[i];
}
}
// 加入arr2中不在并集中的元素
for (int i = 0; i < len2; i++) {
if (!isInArray(unionArr, idx, arr2[i])) {
unionArr[idx++] = arr2[i];
}
}
return idx; // 并集长度
}
int main() {
int len1, len2, unionArr[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 unionLen = getUnion(arr1, len1, arr2, len2, unionArr);
printf("两个数组的并集(去重):");
for (int i = 0; i < unionLen; i++) {
printf("%d ", unionArr[i]);
}
printf("\n并集长度:%d\n", unionLen);
return 0;
}
题42:进制转换(十进制转八进制)
题目描述
输入一个非负整数n(0≤n≤1000),将其转换为八进制数并输出。手动实现转换逻辑,处理n=0的特殊情况,不使用库函数。
C语言实现
c
#include <stdio.h>
void decimalToOctal(int n) {
if (n == 0) {
printf("0");
return;
}
int stack[32], top = -1; // 栈存储八进制位
while (n > 0) {
stack[++top] = n % 8;
n = n / 8;
}
// 出栈输出
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("对应的八进制数:");
decimalToOctal(n);
printf("\n");
return 0;
}
题43:八进制转十进制
题目描述
输入一个八进制字符串(长度≤10,仅含0-7),将其转换为十进制整数并输出。处理前导零情况,验证输入合法性。
C语言实现
c
#include <stdio.h>
#include <string.h>
#include <math.h>
int octalToDecimal(char octal[]) {
int len = strlen(octal);
int decimal = 0;
for (int i = 0; i < len; i++) {
decimal += (octal[i] - '0') * pow(8, len - 1 - i);
}
return decimal;
}
int main() {
char octal[11];
printf("请输入八进制字符串(仅含0-7):");
scanf("%s", octal);
// 验证输入合法性
for (int i = 0; i < strlen(octal); i++) {
if (octal[i] < '0' || octal[i] > '7') {
printf("输入无效,需为八进制字符串\n");
return 1;
}
}
int decimal = octalToDecimal(octal);
printf("对应的十进制数:%d\n", decimal);
return 0;
}
题44:希尔排序(升序)
题目描述
输入一个长度为n(1≤n≤100)的整数数组,使用希尔排序算法将数组按升序排列后输出。希尔排序逻辑:按增量分组,每组插入排序,逐步减小增量至1。
C语言实现
c
#include <stdio.h>
void shellSort(int arr[], int n) {
// 增量逐步减半
for (int gap = n / 2; gap > 0; gap /= 2) {
// 分组插入排序
for (int i = gap; i < n; i++) {
int key = arr[i];
int j = i - gap;
while (j >= 0 && arr[j] > key) {
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = key;
}
}
}
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]);
}
shellSort(arr, n);
printf("升序排列后的数组:");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
题45:求一个数的所有真因子
题目描述
输入一个正整数n(2≤n≤1000),输出该数的所有真因子(不包括自身,包括1),按从小到大的顺序排列。
C语言实现
c
#include <stdio.h>
void printProperFactors(int n) {
printf("%d的真因子:", n);
for (int i = 1; i <= n / 2; i++) {
if (n % i == 0) {
printf("%d ", i);
}
}
printf("\n");
}
int main() {
int n;
printf("请输入正整数n:");
scanf("%d", &n);
if (n < 2 || n > 1000) {
printf("输入无效,n需在2~1000之间\n");
return 1;
}
printProperFactors(n);
return 0;
}
题46:字符串截取(不使用strncpy)
题目描述
输入一个字符串s、起始下标start和截取长度len,手动实现字符串截取功能(从start开始截取len个字符),不使用strncpy,输出截取后的字符串。处理边界情况(start超出范围、len超出剩余长度)。
C语言实现
c
#include <stdio.h>
#include <string.h>
void myStrncpy(char dest[], char src[], int start, int len) {
int srcLen = strlen(src);
int idx = 0;
// 处理start超出范围
if (start >= srcLen) {
dest[0] = '\0';
return;
}
// 截取len个字符,或剩余所有字符
for (int i = start; i < srcLen && idx < len; i++) {
dest[idx++] = src[i];
}
dest[idx] = '\0';
}
int main() {
char s[101], sub[101];
int start, len;
printf("请输入字符串:");
scanf("%s", s);
printf("请输入起始下标和截取长度:");
scanf("%d %d", &start, &len);
if (start < 0 || len < 0) {
printf("起始下标和长度需非负\n");
return 1;
}
myStrncpy(sub, s, start, len);
printf("截取后的字符串:%s\n", sub);
return 0;
}
题47:递归实现阶乘求和
题目描述
输入一个正整数n(1≤n≤10),使用递归算法计算1! + 2! + ... + n! 的和,输出结果。
C语言实现
c
#include <stdio.h>
// 递归求n的阶乘
long long factorial(int n) {
if (n == 1) {
return 1;
}
return n * factorial(n - 1);
}
// 递归求阶乘和
long long factorialSum(int n) {
if (n == 1) {
return 1;
}
return factorial(n) + factorialSum(n - 1);
}
int main() {
int n;
printf("请输入正整数n:");
scanf("%d", &n);
if (n < 1 || n > 10) {
printf("输入无效,n需在1~10之间\n");
return 1;
}
long long sum = factorialSum(n);
printf("1!+2!+...+%d! = %lld\n", n, sum);
return 0;
}
题48:打印等腰梯形(星号)
题目描述
输入一个正整数n(2≤n≤5),打印一个上底为n、下底为2n-1、高为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 bottom = 2 * n - 1; // 下底长度
int height = n; // 高度(行数)
// 逐行打印,每行星号数递增1,空格数递减1
for (int i = 0; i < height; i++) {
// 打印左侧空格,使梯形居中
for (int j = 0; j < (bottom - (n + i)) / 2; j++) {
printf(" ");
}
// 打印星号,当前行星号数 = 上底 + 行数i
for (int j = 0; j < n + i; j++) {
printf("*");
}
printf("\n");
}
return 0;
}
题49:统计字符串中大写字母出现次数
题目描述
输入一个字符串(长度≤100,含大小写字母、数字、空格、标点),统计字符串中大写英文字母(A-Z)的出现次数,忽略其他字符,输出结果。
C语言实现
c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main() {
char str[101];
int count = 0;
printf("请输入字符串:");
getchar(); // 吸收换行符
fgets(str, 101, stdin);
str[strcspn(str, "\n")] = '\0';
for (int i = 0; i < strlen(str); i++) {
if (isupper(str[i])) { // 判断是否为大写字母
count++;
}
}
printf("字符串中大写字母出现次数:%d\n", count);
return 0;
}
题50:数组元素左移k位
题目描述
输入一个长度为n(1≤n≤100)的整数数组和一个整数k(1≤k≤n),将数组元素向左平移k位(循环左移),输出平移后的数组。例如:数组[1,2,3,4,5]左移2位后为[3,4,5,1,2]。
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 leftShift(int arr[], int n, int k) {
k = k % n; // 处理k>n的情况
reverse(arr, 0, k - 1); // 反转前k位
reverse(arr, k, n - 1); // 反转剩余部分
reverse(arr, 0, 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]);
}
leftShift(arr, n, k);
printf("左移%d位后的数组:", k);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
题51:判断一个数是否为平方数
题目描述
输入一个非负整数n(0≤n≤10⁶),判断该数是否为完全平方数(存在整数x使得x²=n),优化算法减少循环次数。
C语言实现
c
#include <stdio.h>
#include <math.h>
int isPerfectSquare(int n) {
if (n < 0) {
return 0;
}
if (n == 0 || n == 1) {
return 1;
}
int left = 1, right = n / 2;
// 二分查找优化
while (left <= right) {
long long mid = (left + right) / 2; // 用long long避免溢出
long long square = mid * mid;
if (square == n) {
return 1;
} else if (square < n) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return 0;
}
int main() {
int n;
printf("请输入非负整数n:");
scanf("%d", &n);
if (n < 0 || n > 1e6) {
printf("输入无效,n需在0~1000000之间\n");
return 1;
}
if (isPerfectSquare(n)) {
printf("%d是完全平方数\n", n);
} else {
printf("%d不是完全平方数\n", n);
}
return 0;
}
题52:字符串大小写转换
题目描述
输入一个字符串(长度≤100,含大小写字母、数字、空格),将字符串中的大写字母转为小写,小写字母转为大写,其他字符不变,输出转换后的字符串。手动实现转换逻辑,不使用toupper/tolower。
C语言实现
c
#include <stdio.h>
#include <string.h>
void swapCase(char str[]) {
int len = strlen(str);
for (int i = 0; i < len; i++) {
// 大写转小写:ASCII码+32
if (str[i] >= 'A' && str[i] <= 'Z') {
str[i] += 32;
}
// 小写转大写:ASCII码-32
else if (str[i] >= 'a' && str[i] <= 'z') {
str[i] -= 32;
}
// 其他字符不变
}
}
int main() {
char str[101];
printf("请输入字符串:");
getchar();
fgets(str, 101, stdin);
str[strcspn(str, "\n")] = '\0';
swapCase(str);
printf("大小写转换后的字符串:%s\n", str);
return 0;
}
题53:递归实现数组求和
题目描述
输入一个长度为n(1≤n≤100)的整数数组,使用递归算法计算数组所有元素的和,输出结果。
C语言实现
c
#include <stdio.h>
// 递归求数组和,index为当前处理的下标
int arraySum(int arr[], int index, int n) {
if (index == n - 1) {
return arr[index]; // 递归终止,最后一个元素
}
return arr[index] + arraySum(arr, index + 1, n);
}
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]);
}
int sum = arraySum(arr, 0, n);
printf("数组所有元素的和:%d\n", sum);
return 0;
}
题54:打印平行四边形(星号)
题目描述
输入一个正整数n(2≤n≤5),打印一个底和高均为n的平行四边形,由星号组成。例如n=3时,图案如下:
(注:每行前有n-1个空格,星号数为n)
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 spaceNum = n - 1; // 每行前的空格数
for (int i = 0; i < n; i++) {
// 打印空格
for (int j = 0; j < spaceNum; j++) {
printf(" ");
}
// 打印星号
for (int j = 0; j < n; j++) {
printf("*");
}
printf("\n");
}
return 0;
}
题55:计算两个数的最小公倍数(非递归版)
题目描述
输入两个正整数a、b(1≤a,b≤10⁶),使用非递归辗转相除法求最大公约数,再计算最小公倍数,避免整数溢出,输出结果。
C语言实现
c
#include <stdio.h>
// 非递归辗转相除法求GCD
long long gcd(long long a, long long b) {
while (b != 0) {
long long temp = b;
b = a % b;
a = temp;
}
return a;
}
// 求LCM,先除后乘避免溢出
long long lcm(long long a, long long b) {
return (a / gcd(a, b)) * b;
}
int main() {
long long a, b;
printf("请输入两个正整数:");
scanf("%lld %lld", &a, &b);
if (a < 1 || b < 1) {
printf("输入无效,请输入正整数\n");
return 1;
}
printf("最小公倍数(LCM):%lld\n", lcm(a, b));
return 0;
}
题56:字符串去空格(首尾+中间)
题目描述
输入一个字符串(长度≤100),删除字符串中所有空格(包括首尾空格和中间空格),原地修改,输出处理后的字符串。
C语言实现
c
#include <stdio.h>
#include <string.h>
void removeSpace(char str[]) {
int idx = 0;
int len = strlen(str);
for (int i = 0; i < len; i++) {
if (str[i] != ' ') {
str[idx++] = str[i];
}
}
str[idx] = '\0'; // 加上结束符
}
int main() {
char str[101];
printf("请输入字符串:");
getchar();
fgets(str, 101, stdin);
str[strcspn(str, "\n")] = '\0';
removeSpace(str);
printf("删除所有空格后的字符串:%s\n", str);
return 0;
}
题57:求数组中第二大的数
题目描述
输入一个长度为n(2≤n≤100)的整数数组,数组元素互不相同,找出数组中第二大的数,输出结果。遍历一次数组完成查找。
C语言实现
c
#include <stdio.h>
int findSecondMax(int arr[], int n) {
int max1, max2;
// 初始化最大值和第二大值
if (arr[0] > arr[1]) {
max1 = arr[0];
max2 = arr[1];
} else {
max1 = arr[1];
max2 = arr[0];
}
// 遍历剩余元素
for (int i = 2; i < n; i++) {
if (arr[i] > max1) {
max2 = max1;
max1 = arr[i];
} else if (arr[i] > max2) {
max2 = arr[i];
}
}
return max2;
}
int main() {
int n;
printf("请输入数组长度:");
scanf("%d", &n);
if (n < 2 || n > 100) {
printf("输入无效,长度需在2~100之间\n");
return 1;
}
int arr[100];
printf("请输入数组元素(互不相同):");
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
int secondMax = findSecondMax(arr, n);
printf("数组中第二大的数:%d\n", secondMax);
return 0;
}
题58:递归实现二进制转十进制
题目描述
输入一个二进制字符串(长度≤10,仅含0和1),使用递归算法将其转换为十进制整数,输出结果。
C语言实现
c
#include <stdio.h>
#include <string.h>
// 递归转换,index为当前处理的下标
long long binaryToDecimalRecursive(char binary[], int index, int len) {
if (index == len - 1) {
return binary[index] - '0'; // 最后一位直接返回
}
// 当前位值 + 后续位值*2
return (binary[index] - '0') * (1LL << (len - 1 - index)) + binaryToDecimalRecursive(binary, index + 1, len);
}
int main() {
char binary[11];
printf("请输入二进制字符串(仅含0和1):");
scanf("%s", binary);
// 验证输入合法性
int len = strlen(binary);
for (int i = 0; i < len; i++) {
if (binary[i] != '0' && binary[i] != '1') {
printf("输入无效,需为二进制字符串\n");
return 1;
}
}
long long decimal = binaryToDecimalRecursive(binary, 0, len);
printf("对应的十进制数:%lld\n", decimal);
return 0;
}
题59:打印空心菱形(星号)
题目描述
输入一个正整数n(3≤n≤10),打印一个边长为n的空心菱形,由星号组成,边框为*,内部为空格。例如n=3时,图案如下:
C语言实现
c
#include <stdio.h>
int main() {
int n;
printf("请输入空心菱形边长n:");
scanf("%d", &n);
if (n < 3 || n > 10) {
printf("输入无效,边长需在3~10之间\n");
return 1;
}
// 上半部分(包括中间行)
for (int i = 1; i <= n; i++) {
// 打印空格
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
// 打印星号:首末位为*,中间为空格(除中间行外)
for (int j = 1; j <= 2 * i - 1; j++) {
if (j == 1 || j == 2 * i - 1 || i == n) {
printf("*");
} else {
printf(" ");
}
}
printf("\n");
}
// 下半部分
for (int i = n - 1; i >= 1; i--) {
// 打印空格
for (int j = 1; j <= n - i; j++) {
printf(" ");
}
// 打印星号:首末位为*,中间为空格
for (int j = 1; j <= 2 * i - 1; j++) {
if (j == 1 || j == 2 * i - 1) {
printf("*");
} else {
printf(" ");
}
}
printf("\n");
}
return 0;
}
题60:删除数组中指定元素(所有出现)
题目描述
输入一个长度为n(1≤n≤100)的整数数组和一个指定整数x,删除数组中所有值等于x的元素,保留剩余元素的顺序,输出处理后的数组及长度。原地修改,不使用额外数组。
C语言实现
c
#include <stdio.h>
// 删除数组中所有x,返回新长度
int deleteElement(int arr[], int n, int x) {
int idx = 0;
for (int i = 0; i < n; i++) {
if (arr[i] != x) {
arr[idx++] = arr[i];
}
}
return idx;
}
int main() {
int n, x;
printf("请输入数组长度和指定删除元素:");
scanf("%d %d", &n, &x);
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]);
}
int newLen = deleteElement(arr, n, x);
printf("删除元素%d后的数组:", x);
for (int i = 0; i < newLen; i++) {
printf("%d ", arr[i]);
}
printf("\n处理后数组长度:%d\n", newLen);
return 0;
}