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

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

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

全栈工匠发布于 2017/9/13更新于 2026/10/23106 浏览
三数之和: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. 注意事项

更多推荐文章

查看全部
  • IDEA 插件开发:Swing 图形界面设计指南
  • 人工智能与数据分析的关系及 Python Pandas 快速入门
  • Stable Diffusion 原理详解(附代码实现)
  • CANN 技术栈解析:Python、C++ 及算子开发选型指南
  • 飞牛 NAS 更换网络环境后 IP 无法访问的解决方法
  • Docker Logs 命令:从基础到高级日志管理
  • 算法:位运算详解及常用技巧 (& ^ ~ -n n-1)
  • RISC-V 智能家居中控系统开发实战:硬件、固件与通信全链路
  • 人工智能行业产品经理薪资分析与能力要求
  • C++ 协程深度解析:从内部机制到实用场景
  • 数据结构:二叉树基础概念与堆实现详解
  • Linux 进程间通信:命名管道(FIFO)实战与原理
  • SQLyog 13.1.1 安装步骤与 MySQL 连接配置指南
  • 民用无人机新规 2026 年 5 月实施:实名登记与激活要求详解
  • 基于 Java 的药店药品进销存与在线问诊管理系统设计与实现
  • Golang 后端性能优化手册:高级优化技巧
  • Java JDK 21 安装与环境配置指南
  • IDA Pro MCP:用 AI 驱动逆向分析实战
  • 基于 Z-Image 与 ComfyUI 的国产 AIGC 图像生成生态构建
  • C# 业务异常处理:BusException 类设计与使用

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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