C 语言初阶算法习题实战解析
这里整理了五道经典的 C 语言算法题,涵盖了数组操作、字符串处理以及位运算技巧。我们直接切入核心逻辑,看看在实际编码中如何高效解决这些问题。
一、两数之和
题目要求在一个有序数组中找到两个数,使它们的和等于目标值,并返回它们的下标(从 1 开始)。
思路很直接,双重循环遍历即可。不过要注意内存分配,因为需要返回一个动态数组。另外,如果当前数字已经大于目标值,可以直接跳过,毕竟数组是有序的。
int* twoSum(int* numbers, int numbersLen, int target, int* returnSize) {
int* ret = (int*)malloc(sizeof(int) * numbersLen);
for (int i = 0; i < numbersLen; i++) {
if (numbers[i] > target) continue;
for (int j = i + 1; j < numbersLen; j++) {
int sum = numbers[i] + numbers[j];
if (sum == target) {
ret[0] = i + 1;
ret[1] = j + 1;
*returnSize = 2;
return ret;
}
}
}
return NULL;
}
二、珠玑妙算
这道题类似于猜数字游戏,需要统计完全匹配(位置和内容都对)和部分匹配(内容对但位置不对)的数量。
关键点在于避免重复计算。我们可以先标记完全匹配的位置,将其替换为特殊字符(如'0'),这样在后续查找部分匹配时就不会再次计入。
int* masterMind(char* solution, char* guess, int* returnSize) {
int* ret = (int*)malloc(sizeof(int) * 2);
ret[0] = 0; ret[1] = 0;
int len = strlen(solution);
// 统计完全匹配
for (int i = 0; i < len; i++) {
if (solution[i] == guess[i]) {
ret[0]++;
solution[i] = guess[i] = '0';
}
}
// 统计部分匹配
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if (solution[i] == guess[j] && solution[i] != '0') {
ret[1]++;
solution[i] = guess[j] = '0';
break;
}
}
}
*returnSize = 2;
return ret;
}
三、寻找奇数
这道题考察的是异或运算的性质。任何数字与自身异或结果为 0,与 0 异或结果为自身。因此,将数组中所有数字依次异或,成对出现的数字会相互抵消,最终剩下的就是那个唯一不重复的数字。
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int ret = 0;
int m = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &m);
ret ^= m;
}
printf("%d\n", ret);
return 0;
}
四、截取字符串
截取字符串有两种常见方法:一是使用标准库函数 strncpy,二是直接将截断位置设置为字符串结束符 \0。后者更简洁,适合简单场景。
// 方法一:使用 strncpy
#include <stdio.h>
#include <string.h>
int main() {
char str[100];
scanf("%s", str);
int n;
scanf("%d", &n);
char ret[100];
strncpy(ret, str, n);
ret[n] = '\0';
printf("%s\n", ret);
return 0;
}
// 方法二:直接修改结束标志
#include <stdio.h>
int main() {
char str[1000];
scanf("%s", str);
int n = 0;
scanf("%d", &n);
str[n] = '\0';
printf("%s\n", str);
return 0;
}
五、寻找峰值
寻找峰值元素时,边界情况最容易出错。我们需要单独检查首尾元素,然后再遍历中间部分。只要找到一个比左右邻居都大的元素,即为峰值。
int findPeakElement(int* nums, int numsLen) {
// 处理边界情况
if (numsLen <= 1) return 0;
if (nums[0] > nums[1]) return 0;
if (nums[numsLen - 1] > nums[numsLen - 2]) return numsLen - 1;
// 遍历中间元素
for (int i = 1; i < numsLen - 1; i++) {
if (nums[i] > nums[i - 1] && nums[i] > nums[i + 1]) {
return i;
}
}
return -1;
}
以上便是这五道题的完整解析。算法的核心往往不在于代码长短,而在于对数据结构的理解和边界条件的把控。希望这些示例能为你接下来的练习提供一点参考。


