和为0的四元组-双指针法(C语言实现)

目录

一、问题描述

二、双指针法思路

三、C语言代码

四、运行结果

[五、 程序复杂度分析](#五、 程序复杂度分析)


一、问题描述

给定一个整数数组 nums,编写一个函数,找出所有和为0的四元组。你可以不考虑答案的顺序。如:nums = -1, 0, 1, 2, -1, -4,输出:-1,-1,0,2等。

二、双指针法思路

1.排序:使用qsort对数组进行排序,以便后续使用双指针法。

2.固定前两个元素:使用两层循环遍历数组,固定前两个元素arri和arrj。

3.双指针法:对于每对固定的arri和arrj,使用左右指针在剩余元素中寻找和为-(arri+arrj)的两个元素。从left=j+1的下一个往后找,和right=n-1开始往前找,进行匹配。根据sum值与target值大小比较,进行将left向后一个位置或者right向前移动一个位置不断接近target,直至相等或者left 大于right匹配失败。

4.去重处理:在各个层次都加入了去重逻辑,确保每个四元组只输出一次。

三、C语言代码

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>

// 比较函数,用于qsort排序
int compare(const void* a, const void* b) {
    return (*(int*)a - *(int*)b);
}

// 找出所有和为0的四元组并打印
/*
双指针法:对于每对固定的arr[i]和arr[j],使用左右指针在剩余元素中寻找和为 - (arr[i] + arr[j])的两个元素。
从left = j + 1的下一个往后找,和right = n - 1开始往前找,进行匹配。
根据sum值与target值大小比较,进行将left向后一个位置或者right向前移动一个位置不断接近target,
直至相等或者left大于right匹配失败。
*/
void num4sum0(int arr[], int n) {
    if (n < 4) return;  // 数组长度不足,直接返回

    // 先对数组进行排序
    qsort(arr, n, sizeof(int), compare);
    int index = 0;
    // 遍历数组,固定i,j前两个元素
    for (int i = 0; i < n - 3; i++) {       
        // 跳过重复的元素:arr[i] == arr[i - 1]
        if (i > 0 && arr[i] == arr[i - 1]) continue;

        for (int j = i + 1; j < n - 2; j++) {
            // 跳过重复的元素:arr[j] == arr[j - 1]
            if (j > i + 1 && arr[j] == arr[j - 1]) continue;

            int target = -(arr[i] + arr[j]);  // 计算剩余两数的和:从j的下一个往后找,和n-1开始往前找,进行匹配
            int left = j + 1;  // 左指针
            int right = n - 1;  // 右指针

            while (left < right) {
                int sum = arr[left] + arr[right];

                if (sum == target) {
                    // 找到一个四元组,打印
                    printf("%d:(%d, %d, %d, %d)\n", index++, arr[i], arr[j], arr[left], arr[right]);

                    // 跳过重复元素
                    while (left < right && arr[left] == arr[left + 1]) left++;
                    while (left < right && arr[right] == arr[right - 1]) right--;

                    // 移动指针
                    left++;
                    right--;
                }
                else if (sum < target) {//根据sum值与target值大小比较,移动左指针右指针前后一个位置不断接近target,直至相等或者left大于right匹配失败
                    left++;  // 和太小,左指针右移
                }
                else {
                    right--;  // 和太大,右指针左移
                }
            }
        }
    }
}

int main() {
    int arr[] = { -23, 45, -12, 7, 38, -41, 19, -6, 22, -34, 49, -7, 27, -29, 11, 3, -7, 28, 14, -9 };
    int n = sizeof(arr) / sizeof(arr[0]);

    printf("所有和为0的四元组:\n");
    num4sum0(arr, n);

    return 0;
}

四、运行结果

五、 程序复杂度分析

程序的时间复杂度为O (n³),空间复杂度为 O (1)。在保持正确性的前提下,四数之和问题的时间复杂度无法突破 O (n³) 的下界了。

相关推荐
程序猿编码12 分钟前
不用 PyTorch!纯 C 实现 N 维张量 + 反向传播,完成手写数字识别训练
c语言·人工智能·pytorch·神经网络·卷积神经网络·大模型推理
tangguofeng1 小时前
基于分治策略的循环赛日程表问题的思路讲解
算法
hnjzsyjyj1 小时前
洛谷 P1339:[USACO09OCT] Heat Wave G ← Bellman-Ford 算法
数据结构·bellman-ford 算法
起个名字费劲死了1 小时前
VisionMaster集成深度学习算法(基础狗)
人工智能·深度学习·算法
lengxuenong1 小时前
枚举例题分析
c++·算法·青少年编程
Navigator_Z2 小时前
LeetCode //C - 1269. Number of Ways to Stay in the Same Place After Some Steps
c语言·算法·leetcode
2601_965742222 小时前
短视频脚本创作方法分享:本地生活类账号的起步思路
大数据·人工智能·算法·ai·新媒体运营·生活
55873生态系统手记2 小时前
读完 55873 资产钱包的技术栈,我重新理解了 "合规钱包" 应该长什么样
算法·架构
旋生万物2 小时前
素数螺旋映射 $z_n=n^{1+i}$ 的角分布统计检验与零模型对比
大数据·前端·人工智能·算法·云原生·螺旋生成论·螺旋相位
HRTOS2 小时前
HRTOS Shell继续完善:优化printf缓冲区与字符串越界保护,国庆后随新版本更新
运维·单片机·嵌入式硬件·算法·51单片机