LeetCode 16. 最接近的三数之和 3Sum Closest(C语言)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hang404/article/details/84892993

题目描述:

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

题目解答:

方法1:排序+双指针

和三数之和有些类似,先对数组进行排序,外层遍历,内层利用双指针。内层循环中,如果大于target则减小右指针,如果小于target则增大右指针,并将最小差值与当前差值进行比较,判断是否要更新差值。运行时间4ms,代码如下。

int comp(const void* a, const void* b) {
    return (*(int*)a > *(int*)b ? 1 : -1);
}
int threeSumClosest(int* nums, int numsSize, int target) {
    int n = numsSize, i = 0;
    qsort(nums, n, sizeof(int), comp);
    int min = INT_MAX;
    int left = 0, right = 0, temp = 0;
    for(i = 0; i < n - 2; i++) {
        left = i + 1;
        right = n - 1;
        while(left < right) {
            temp = nums[i] + nums[left] + nums[right] - target;
            if(temp > 0)
                right--;
            else if(temp == 0) {
                return target;
            }
            else
                left++;
            if(abs(temp) < abs(min))
                min = temp;
        }
    }
    return target + min;
}

但是数组中可能存在重复元素,所以上述过程中可能多判断了一些,可以进行优化,减少重复情况。需要注意的是内层循环中跳过重复元素是写在判断情况里边的,为什么不将判断left和right重复的循环放在更新最小值的位置呢?因为内层可能会用到两个相同的数。跳过元素可以放在上边的原因是temp与0的关系,比如:比0大,说明应该减小right,与right等值的都不应该用到,而与left等值的可能会用到,所以此时不应该跳过与left等值的。运行时间4ms,代码如下。

int comp(const void* a, const void* b) {
    return (*(int*)a > *(int*)b ? 1 : -1);
}
int threeSumClosest(int* nums, int numsSize, int target) {
    int n = numsSize, i = 0;
    qsort(nums, n, sizeof(int), comp);
    int min = INT_MAX;
    int left = 0, right = 0, temp = 0;
    for(i = 0; i < n - 2; i++) {
        left = i + 1;
        right = n - 1;
        while(left < right) {
            temp = nums[i] + nums[left] + nums[right] - target;
            if(temp > 0) {
                while(nums[right] == nums[right - 1])
                    right--;
                right--;
            }
            else if(temp == 0) {
                return target;
            }
            else {
                while(nums[left] == nums[left + 1])
                    left++;
                left++;
            }
            if(abs(temp) < abs(min))
                min = temp;                
        }
        while(nums[i] == nums[i + 1])
            i++;
    }
    return target + min;
}

猜你喜欢

转载自blog.csdn.net/hang404/article/details/84892993