• leetcode-15.三数之和-20220821


    1. 三数之和
      给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

    注意:答案中不可以包含重复的三元组

    示例 1:

    输入:nums = [-1,0,1,2,-1,-4]
    输出:[[-1,-1,2],[-1,0,1]]
    示例 2:

    输入:nums = []
    输出:[]
    示例 3:

    输入:nums = [0]
    输出:[]

    提示:
    0 <= nums.length <= 3000
    -105 <= nums[i] <= 105

    思考:这个题目是我参考 卡神的做法做出来的,具体网址 https://www.programmercarl.com/ 在这个里面

    首先哈希表的方法可以求出来所有的三元组,但是去重的难度非常大

    使用双指针的方法,可以将算法的时间复杂度降低一个数量级,对代码的效率提升很高

    上代码~

    /**
     * Return an array of arrays of size *returnSize.
     * The sizes of the arrays are returned as *returnColumnSizes array.
     * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
     */
     // 这个题目使用双指针方法进行求解
     // 1、数组进行排序
     // 2、对于 a,选择从开头到结尾进行尝试
     // 3、对b和c,选择从a的后面一个位置和数组的最后一个位置进行查找
     // 4、如果a+b+c>0 说明整体比较大,那么就将c向左移动
     // 5、如果a+b+c<0 说明整体比较小,那么将b向右移动
     // 6、如果a+b+c=0 说明正好是结果,那么输出结果即可 此时b和c都要进行移动,缩小范围
    
    // 那对结果的去重应该如何进行呢?
    
    void quicksort(int* nums, int left, int right)
    {
        if (left > right) return;
        int mid = partition(nums, left, right);
        quicksort(nums, left, mid - 1);
        quicksort(nums, mid+1, right);
    }
    
    
    int partition(int* nums, int left, int right)
    {
        int key = nums[left];
        int first = left;
        int last = right;
        int tmp;
        while(first < last) {
            //先找右边第一个小于key的值的位置
            while(first<last && nums[last] >= key) {
                last--;
            }
            // 再找左边第一个大于key的值的位置
            while(first<last && nums[first] <= key) {
                first++;
            }
            // 交换上面两个数的位置
            if (first < last) {
                tmp = nums[first];
                nums[first] = nums[last];
                nums[last] = tmp;
            }
        }
        // 交换key的位置
        tmp = nums[left];
        nums[left] = nums[first];
        nums[first] = tmp;
        return last;
    }
    
    int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
        quicksort(nums, 0, numsSize - 1);
        int** ans = (int**)malloc(sizeof(int*) * 18000);
        *returnSize = 0; // 多少个符合条件的三元组
        int* col = (int*)malloc(sizeof(int) * 18000);
        *returnColumnSizes = col;
        int a, b, c;
        for (a = 0; a < numsSize - 2; a++) {
            // 对a去重剪枝
            if (nums[a] > 0) break;
            if(a > 0 && nums[a] == nums[a - 1]) {
                continue;
            }
            b = a + 1;
            c = numsSize - 1;
            while(b < c) {
                if (nums[a] + nums[b] + nums[c] < 0) {
                    b++;
                }else if (nums[a] + nums[b] + nums[c] > 0) {
                    c--;
                } else { // 得到的答案
                    // 获取答案 当nums[a] + nums[b] + nums[c] = 0
                    ans[*returnSize] = (int*)malloc(sizeof(int) * 3);
                    ans[*returnSize][0] = nums[a];
                    ans[*returnSize][1] = nums[b];
                    ans[*returnSize][2] = nums[c];
                    col[*returnSize] = 3;
                    (*returnSize)++;
                    // 对b和c的去重
                    while (b < c && nums[c] == nums[c - 1]) c--;
                    while(b < c && nums[b] == nums[b + 1]) b++;
                    b++; // 关键一步,忘了处理了
                    c--;
                } 
            }
        }
        return ans;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    总结:
    1、对基础算法的实现不熟悉,一个快速排序写了半个小时,最后还是参考人家的实现写出来的,后面多用多练
    2、对算法的每个步骤细节没有写清楚,收集答案那块忘了收缩了,然后搞得b和c没有刷新,同时对去重的考虑也不清楚,大脑是混乱的,所以后面写程序的时候所有的步骤实现都写出来,然后再写代码,这样调试的时候会比较快速

  • 相关阅读:
    Linux安装DMETL4
    【实践篇MySQL执行计划详解
    python--数据容器--set(集合)
    栈实现综合计算器(思路分析) [数据结构][Java]
    ython + Selenium Web自动化 2022更新版教程 自动化测试 软件测试 爬虫-笔记博客整理
    用vscode修改代码后运行程序不更新
    灰度:为什么说这次以太坊分叉ETHW可能不可行
    如何设计 DAO 的 PoW 评判标准 并平衡不可能三角
    linux Nginx+Tomcat负载均衡、动静分离
    Mac 使用 Homebrew 安装 Python3
  • 原文地址:https://blog.csdn.net/weixin_38853761/article/details/126447366