LeetCode C语言答案怎么找?

99ANYc3cd6
预计阅读时长 19 分钟
位置: 首页 C语言 正文

为什么在 LeetCode 上用 C 语言刷题?

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

leetcode c语言答案
(图片来源网络,侵删)
  • 深入理解底层原理:C 语言没有 STL(标准模板库)或内置的高效数据结构(如 set, map, dict),你必须手动实现链表、哈希表、树等结构,这能让你深刻理解这些数据结构的内存管理和运作方式。
  • 掌握内存管理:C 语言要求你手动分配和释放内存(malloc, free),这能让你对内存泄漏、野指针等问题有更清晰的认识,这是成为一名优秀程序员的基石。
  • 性能极致:C 语言是编译型语言,运行效率极高,在处理大规模数据时,C 语言的性能优势会非常明显。
  • 面试准备:一些对底层要求较高的岗位(如嵌入式、系统开发)可能会考察 C 语言的编程能力。

LeetCode C 语言环境准备

LeetCode 的在线编辑器已经内置了 C 语言环境,你无需额外配置,你只需要:

  1. 选择语言:在提交代码时,确保语言选择为 "C"。
  2. 包含头文件: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;
    };
  • 二叉树节点:

    leetcode c语言答案
    (图片来源网络,侵删)
    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:两数相加

  • 题目:给你两个非空的链表,表示两个非负整数,它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字,请你将两个数相加,并以相同形式返回一个表示和的链表。

    leetcode c语言答案
    (图片来源网络,侵删)
  • 思路:模拟竖式加法,同时处理进位。

  • 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 语言刷题技巧与注意事项

  1. 善用哨兵节点:在处理链表时,创建一个虚拟头节点(dummy head)可以大大简化代码逻辑,避免处理头节点为空的特殊情况。
  2. 数组模拟哈希表:如示例 2 所示,对于字符、小整数等键,使用数组模拟哈希表是 C 语言中非常高效和常见的技巧。
  3. 边界条件检查:C 语言没有自动的空指针检查,在访问指针(如 head->next)或数组(如 arr[i])之前,务必检查其是否为 NULL 或越界,否则会导致程序崩溃。
  4. 内存泄漏:在 main 函数或测试代码中,如果你用 malloc 创建了数据结构,记得在用完后 free 掉,LeetCode 的评测系统会处理,但本地测试时养成好习惯。
  5. 整数溢出:在进行加减乘除运算时,结果可能会超过 int 的范围(约 21 亿),可以使用 long long 类型(64位整数)来存储中间结果,或者在每次运算前检查是否会溢出。
    // 检查加法溢出
    if (a > INT_MAX - b) {
        // 溢出处理
    }

推荐资源

  • LeetCode 官方:直接在 LeetCode 网站上选择 "C" 语言进行练习。
  • 《C Primer Plus》:经典的 C 语言入门和进阶书籍。
  • 《数据结构与算法分析:C 语言描述》:结合 C 语言学习数据结构与算法的经典教材。

希望这份指南能帮助您开始在 LeetCode 上使用 C 语言进行算法练习!祝您刷题愉快!

-- 展开阅读全文 --
头像
initlist函数在C语言中如何实现?
« 上一篇 01-24
Huffman解码C语言实现有哪些关键步骤?
下一篇 » 01-24

相关文章

取消
微信二维码
支付宝二维码

目录[+]