为什么在 LeetCode 上用 C 语言刷题?
虽然 C++ 和 Python 因其强大的标准库和灵活性而更受欢迎,但 C 语言在算法学习中有其独特的优势:

(图片来源网络,侵删)
- 深入理解底层原理:C 语言没有 STL(标准模板库)或内置的高效数据结构(如
set,map,dict),你必须手动实现链表、哈希表、树等结构,这能让你深刻理解这些数据结构的内存管理和运作方式。 - 掌握内存管理:C 语言要求你手动分配和释放内存(
malloc,free),这能让你对内存泄漏、野指针等问题有更清晰的认识,这是成为一名优秀程序员的基石。 - 性能极致:C 语言是编译型语言,运行效率极高,在处理大规模数据时,C 语言的性能优势会非常明显。
- 面试准备:一些对底层要求较高的岗位(如嵌入式、系统开发)可能会考察 C 语言的编程能力。
LeetCode C 语言环境准备
LeetCode 的在线编辑器已经内置了 C 语言环境,你无需额外配置,你只需要:
- 选择语言:在提交代码时,确保语言选择为 "C"。
- 包含头文件:C 语言的代码需要包含必要的头文件,最常用的是:
#include <stdlib.h>:用于malloc,free,calloc等内存分配函数。#include <string.h>:用于strlen,strcpy,memset等字符串和内存操作函数。#include <limits.h>:用于INT_MAX,INT_MIN等整数极限值。
C 语言解题核心要素
1 结构体定义
LeetCode 中很多题目会用到自定义的结构体,比如链表节点、二叉树节点等。
-
链表节点:
struct ListNode { int val; struct ListNode *next; }; -
二叉树节点:
(图片来源网络,侵删)struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; };
2 内存管理
这是 C 语言刷题的关键,你需要为动态创建的节点或数组分配内存。
malloc(size_t size):分配size字节的内存块。calloc(size_t num, size_t size):分配num个长度为size的字节内存块,并初始化为 0。- *`free(void ptr)`释放之前分配的内存块,防止内存泄漏**。
示例:创建一个新链表节点
struct ListNode* createNode(int val) {
struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));
if (newNode == NULL) {
// 处理内存分配失败的情况
exit(1);
}
newNode->val = val;
newNode->next = NULL;
return newNode;
}
3 辅助函数
为了方便测试和调试,你通常会需要一些辅助函数来构建输入和验证输出。
- 创建链表:根据数组创建一个链表。
- 打印链表:遍历并打印链表内容,方便查看结果。
- 释放链表:在测试完成后,释放链表占用的内存。
经典题型 C 语言实现示例
示例 1:两数相加
-
题目:给你两个非空的链表,表示两个非负整数,它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字,请你将两个数相加,并以相同形式返回一个表示和的链表。
(图片来源网络,侵删) -
思路:模拟竖式加法,同时处理进位。
-
C 语言代码:
#include <stdlib.h> // Definition for singly-linked list. struct ListNode { int val; struct ListNode *next; }; struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) { struct ListNode *dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode)); dummyHead->next = NULL; struct ListNode *current = dummyHead; int carry = 0; while (l1 != NULL || l2 != NULL || carry != 0) { int sum = carry; if (l1 != NULL) { sum += l1->val; l1 = l1->next; } if (l2 != NULL) { sum += l2->val; l2 = l2->next; } carry = sum / 10; struct ListNode *newNode = (struct ListNode*)malloc(sizeof(struct ListNode)); newNode->val = sum % 10; newNode->next = NULL; current->next = newNode; current = current->next; } struct ListNode *result = dummyHead->next; free(dummyHead); // 释放哨兵节点 return result; }
示例 2:无重复字符的最长子串
-
题目:给定一个字符串
s,请你找出其中不含有重复字符的最长子串的长度。 -
思路:使用滑动窗口和哈希表,C 语言中没有内置的哈希表,我们可以使用一个大小为 128(ASCII字符集大小)的整型数组来模拟哈希表,记录每个字符最后一次出现的位置。
-
C 语言代码:
#include <string.h> int lengthOfLongestSubstring(char* s) { int charIndex[128]; // 存储字符最后一次出现的索引 memset(charIndex, -1, sizeof(charIndex)); // 初始化为-1 int maxLength = 0; int left = 0; // 滑动窗口的左边界 for (int right = 0; s[right] != '\0'; right++) { char currentChar = s[right]; // 如果字符已存在于窗口内,更新左边界 // charIndex[currentChar] + 1 是为了避免字符重复时,left回退到更早的位置 if (charIndex[currentChar] >= left) { left = charIndex[currentChar] + 1; } // 更新字符的最新位置 charIndex[currentChar] = right; // 更新最大长度 int currentLength = right - left + 1; if (currentLength > maxLength) { maxLength = currentLength; } } return maxLength; }
示例 3:反转链表
-
题目:给你单链表的头节点
head,请你反转链表,并返回反转后的链表头节点。 -
思路:使用迭代法,三个指针
prev,curr,next不断翻转指针方向。 -
C 语言代码:
#include <stdlib.h> struct ListNode { int val; struct ListNode *next; }; struct ListNode* reverseList(struct ListNode* head) { struct ListNode *prev = NULL; struct ListNode *curr = head; while (curr != NULL) { // 1. 暂存下一个节点 struct ListNode *nextTemp = curr->next; // 2. 翻转当前节点的指针 curr->next = prev; // 3. prev 和 curr 后移 prev = curr; curr = nextTemp; } // 当循环结束时,prev 指向新的头节点 return prev; }
C 语言刷题技巧与注意事项
- 善用哨兵节点:在处理链表时,创建一个虚拟头节点(
dummy head)可以大大简化代码逻辑,避免处理头节点为空的特殊情况。 - 数组模拟哈希表:如示例 2 所示,对于字符、小整数等键,使用数组模拟哈希表是 C 语言中非常高效和常见的技巧。
- 边界条件检查:C 语言没有自动的空指针检查,在访问指针(如
head->next)或数组(如arr[i])之前,务必检查其是否为NULL或越界,否则会导致程序崩溃。 - 内存泄漏:在
main函数或测试代码中,如果你用malloc创建了数据结构,记得在用完后free掉,LeetCode 的评测系统会处理,但本地测试时养成好习惯。 - 整数溢出:在进行加减乘除运算时,结果可能会超过
int的范围(约 21 亿),可以使用long long类型(64位整数)来存储中间结果,或者在每次运算前检查是否会溢出。// 检查加法溢出 if (a > INT_MAX - b) { // 溢出处理 }
推荐资源
- LeetCode 官方:直接在 LeetCode 网站上选择 "C" 语言进行练习。
- 《C Primer Plus》:经典的 C 语言入门和进阶书籍。
- 《数据结构与算法分析:C 语言描述》:结合 C 语言学习数据结构与算法的经典教材。
希望这份指南能帮助您开始在 LeetCode 上使用 C 语言进行算法练习!祝您刷题愉快!
