跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C算法

三数之和:C 语言双指针解法详解

三数之和是经典的数组处理问题,核心在于寻找三个元素使其和为零且结果不重复。解决方案采用排序加双指针策略,时间复杂度控制在 O(n^2)。代码使用 C 语言实现动态内存分配,通过跳过重复元素避免冗余计算。重点在于边界条件处理和去重逻辑的严谨性,适合用于理解算法优化与内存管理。

全栈工匠发布于 2017/9/13更新于 2026/6/1223 浏览
三数之和:C 语言双指针解法详解

三数之和:C 语言双指针解法详解

给定一个包含 n 个整数的数组 nums,判断是否存在三个元素 a, b, c,使得 a + b + c = 0?找出所有满足条件且不重复的三元组。

例如,输入 [-1, 0, 1, 2, -1, -4],输出 [[-1, 0, 1], [-1, -1, 2]]。

核心难点

解决这道题主要面临两个挑战:一是如何高效地存储结果并避免重复,二是如何在保证正确性的前提下降低时间复杂度。暴力枚举的时间复杂度为 O(n³),容易超时,因此需要更优的策略。

解题思路

1. 排序预处理

首先对数组进行升序排序。排序后,相同的数字会相邻,这为后续的去重操作提供了便利。虽然冒泡排序实现简单,但在数据量较大时效率不如快速排序,不过对于理解双指针逻辑来说足够清晰。

2. 双指针扫描

固定第一个数 nums[i],然后使用两个指针 begin 和 end 分别指向剩余部分的头部和尾部。

  • 如果三数之和等于 0,记录结果,并向内移动两个指针。
  • 如果和大于 0,说明右端数值过大,end 左移。
  • 如果和小于 0,说明左端数值过小,begin 右移。

3. 去重处理

为了避免重复三元组,需要在循环中跳过相同的数字:

  • 外层循环中,若当前数字与前一个相同,则跳过。
  • 找到有效组合后,移动指针时需跳过所有连续相同的值。

代码实现

以下是完整的 C 语言实现,包含动态内存分配和必要的注释说明。

/**
 * Return an array of arrays of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */

/* 冒泡排序辅助函数 */
void bubblesort(int *nums, int numsSize) {
    int i, j;
    int temp;
    int flag = 1;
    
    for (i = 0; i < numsSize; i++) {
        for (j = 0; j < numsSize - 1; j++) {
            if (nums[j + 1] < nums[j]) {
                temp = nums[j + 1];
                nums[j + 1] = nums[j];
                nums[j] = temp;
                flag = 0;
            }
        }
        if (flag == 1)
            break;
    }
}

int** threeSum(int* nums, int numsSize, int* returnSize) {
    // 预估最大空间,实际使用时根据返回数量调整
    int** result = (int**)malloc(sizeof(int*) * (numsSize * (numsSize - 1) * (numsSize - 2)) / 6);  
    int i, begin, end;
    int m = 0;
    int sum;
    
    if (numsSize < 3) {
        *returnSize = 0;
        return NULL;
    }
    
    // 先排序
    bubblesort(nums, numsSize);

    for (i = 0; i < numsSize - 2; i++) {
        // 优化:如果当前数大于 0,后面不可能和为 0
        if (nums[i] > 0)
            break;
        
        // 去重:跳过重复的第一个数
        if (i > 0 && nums[i] == nums[i - 1])
            continue;
            
        begin = i + 1;
        end = numsSize - 1;
        
        while (begin < end) {
            sum = nums[i] + nums[begin] + nums[end];
            
            if (sum == 0) {
                // 分配单个三元组的空间
                result[m] = (int*)malloc(sizeof(int) * 3);  
                result[m][0] = nums[i];
                result[m][1] = nums[begin];
                result[m][2] = nums[end];
                m++;
                
                begin++;
                end--;
                
                // 去重:跳过重复的第二个数
                while (begin < end && nums[begin] == nums[begin - 1]) {
                    begin++;
                }
                // 去重:跳过重复的第三个数
                while (begin < end && nums[end] == nums[end + 1]) {
                    end--;
                }
            } else if (sum > 0) {
                end--;
            } else {
                begin++;
            }
        }
    }
    
    *returnSize = m;  
    return result;       
}

注意事项

  1. 内存管理:C 语言中手动管理内存是关键。这里使用了 malloc 分配二维数组结构,调用方需负责释放内存。
  2. 边界检查:当数组长度小于 3 时直接返回空结果,避免非法访问。
  3. 性能权衡:示例中使用冒泡排序是为了展示基础逻辑,实际工程中建议使用标准库中的 qsort 以获得更好的性能。

这个方案将时间复杂度优化到了 O(n²),空间复杂度取决于结果集的大小。通过合理的去重逻辑,确保了输出的唯一性。

目录

  1. 三数之和:C 语言双指针解法详解
  2. 核心难点
  3. 解题思路
  4. 1. 排序预处理
  5. 2. 双指针扫描
  6. 3. 去重处理
  7. 代码实现
  8. 注意事项
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于Termux的Android平台OpenClaw部署:移动端AI助理实现
  • 智谱 GLM-5 旗舰模型开源及昇腾部署指南
  • 基于 AR 眼镜的喝水提醒应用开发实践
  • 开源大模型涨价策略分析:Llama 3.5 与 GLM-5 商业化博弈
  • GitHub Copilot Pro 学生认证免费订阅及 VS Code 集成教程
  • 基于 Nexent 构建智能烹饪顾问:知识库与 MCP 工具实战
  • 数学与计算机:逻辑与算法的浪漫邂逅
  • 从源码看 ArrayList 与 LinkedList 的性能差异
  • Prometheus 集成 Python 业务指标的三种主流方案及代码示例
  • OpenClaw 进阶教程:记忆系统、定时任务、多模型与子代理解析
  • Spring AI MCP Server 集成与实现
  • 基于 Python 和 UniApp 的理疗店服务预约系统设计与实现
  • Web 数据管理:爬虫、网页分析与文本处理技术详解
  • 具身智能发展瓶颈:AI 数据生成的解决方案与趋势
  • OpenRouter 详解:全球 AI 模型聚合平台与免费资源指南
  • Python 深浅拷贝详解:原理、实现与适用场景
  • MySQL 8.0 Windows 版本压缩包安装与配置指南
  • 国产编程字体 Sarasa-Gothic(更纱黑体)深度测评与配置指南
  • Spring 配置文件与 MyBatis 核心用法
  • OpenClaw 开源项目实战:打造专属 AI 伴侣与图像生成

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online