打卡 DAY 21 三数之和

力扣原题链接

一、题目描述

二、思路

双指针法: 

先对数组进行排序,将无序数组变为有序数组;接着设置三个指针i、left、right,进行如下操作: 

首先判断 i 指针,若nums[ i ] > 0,则整个数组找不出满足条件的三元组,跳出循环;若满足 ( i > 0 && nums[ i ] == nums[ i - 1] ),则移动 i 至 nums[ i ] != nums[ i - 1] 处。当 nums[ i ] + nums[ left ] + nums[ right ] < 0 时,将 left 指针向右移动,以此来增大 nums[ left ] 的值,从而使和接近 0 ;同理,当 nums[ i ] + nums[ left ] + nums[ right ] > 0 时,将right指针向左移动,直到 right 与 left 指针相遇为止;当 nums[ i ] + nums[ left ] + nums[ right ] == 0 时,记录三元组,并移动 left 指针直到 nums[ left ] != nums[ left - 1 ] 为止,同理,移动 right 指针直到nums[ right ] != nums[ right + 1 ],从而保证不会得到重复的三元组。

三、解题过程

  • 实现快速排序接口函数

void swap(int* arr, int a, int b){
    int tmp = arr[a];
    arr[a] = arr[b];
    arr[b] = tmp;
}

void QuickSort(int* arr, int begin, int end){
    if(begin >= end) return ;
    int key = arr[begin];
    int left = begin;
    int right = end;
    while(left < right){
        while(nums[right] >= key && left < right) right --;
        while(nums[left] < key && left < right) left ++;
        swap(arr, left, right);
    }
    swap(arr, left, begin);
    QuickSort(arr, begin, left);
    QuickSort(arr, left + 1,end);
}
  • 处理数组并初始化各个变量

    QuickSort(nums,0 ,numsSize - 1);
    int** cnt = (int**)malloc(sizeof(int*) * 18000);
    int index = 0;
    int left, right;
    int i = 0;
  • 进入循环

    for(; i < numsSize - 2; i ++){
        //当nums[i]大于0时,三数之和不可能为零
        if(nums[i] > 0) break;
        //移动 i 至 nums[ i ] != nums[ i - 1] 处,保证不会得到重复的三元组
        if(i > 0 && nums[i] == nums[i - 1]) continue;
        //更新left和right的值
        left = i + 1;
        right = numsSize - 1;
        //进入循环,找到所有不重复的三元组
        while(left < right){
            int sum = nums[i] + nums[left] + nums[right];
            //当三数之和小于零时,将left指针右移
            if(sum < 0) left ++;
            //当三数之和大于零时,将right指针左移
            else if(sum > 0) right --;
            //当三数之和等于零时,更新输出数组
            else{
                int* arr = (int*)malloc(sizeof(int) * 3);
                arr[0] = nums[i];
                arr[1] = nums[left];
                arr[2] = nums[right];
                (cnt)[index ++] = arr;
                //移动 left 指针直到 nums[left] != nums[left - 1] 为止
                while(left < right && nums[left] == nums[left + 1]) left ++;
                //移动 right 指针直到nums[ right ] != nums[ right + 1 ]
                while(left < right && nums[right] == nums[right - 1]) right --;
                //更新left和right
                left ++;
                right --;
            }
        }
    }
  • 更新二维数组的大小并输出数组

    *returnSize = index;
    *returnColumnSizes = (int*)malloc(sizeof(int) * index);
    for(int j = 0; j < index; j ++){
        (*returnColumnSizes)[j] = 3;
    }
    return cnt;

四、代码

/**
 * 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().
 */

void swap(int* arr, int a, int b){
    int tmp = arr[a];
    arr[a] = arr[b];
    arr[b] = tmp;
}

void QuickSort(int* arr, int begin, int end){
    if(begin >= end) return ;
    int key = arr[begin];
    int left = begin;
    int right = end;
    while(left < right){
        while(arr[right] >= key && left < right) right --;
        while(arr[left] < key && left < right) left ++;
        swap(arr, left, right);
    }
    swap(arr, left, begin);
    QuickSort(arr, begin, left);
    QuickSort(arr, left + 1,end);
}


int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    QuickSort(nums,0 ,numsSize - 1);
    int** cnt = (int**)malloc(sizeof(int*) * 18000);
    int index = 0;
    int left, right;
    int i = 0;

    for(; i < numsSize - 2; i ++){
        if(nums[i] > 0) break;
        if(i > 0 && nums[i] == nums[i - 1]) continue;
        left = i + 1;
        right = numsSize - 1;
        while(left < right){
            int sum = nums[i] + nums[left] + nums[right];
            if(sum < 0) left ++;
            else if(sum > 0) right --;
            else{
                int* arr = (int*)malloc(sizeof(int) * 3);
                arr[0] = nums[i];
                arr[1] = nums[left];
                arr[2] = nums[right];
                (cnt)[index ++] = arr;
                while(left < right && nums[left] == nums[left + 1]) left ++;
                while(left < right && nums[right] == nums[right - 1]) right --;
                left ++;
                right --;
            }
        }
    }

    *returnSize = index;
    *returnColumnSizes = (int*)malloc(sizeof(int) * index);
    for(int j = 0; j < index; j ++){
        (*returnColumnSizes)[j] = 3;
    }
    return cnt;
}

时间复杂度:O(n^2)。

五、遇到的问题

  • 一开始完全没思路。。。
  • 去重的那块绕了好久才绕明白
  • 对cnt的动态内存分配不理解为什么是*18000,确实17000之类的小于18000的没能通过,但是,为啥?答案也给的18000,但也没解释。我不李姐。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值