• [Leetcode] Sum 系列


    Sum 系列题解

    Two Sum题解

    题目来源:https://leetcode.com/problems/two-sum/description/

    Description

    Given an array of integers, return indices of the two numbers such that they add up to a specific target.

    You may assume that each input would have exactly one solution, and you may not use the same element twice.

    Example

    Given nums = [2, 7, 11, 15], target = 9,
    
    Because nums[0] + nums[1] = 2 + 7 = 9,
    return [0, 1].
    

    Solution

    /**
     * Note: The returned array must be malloced, assume caller calls free().
     */
    int* twoSum(int* nums, int numsSize, int target) {
        int* result = (int*)malloc(2 * sizeof(int));
    
        int i, j;
        for (i = 0; i < numsSize; i++) {
        	for (j = 0; j < numsSize; j++) {
        		if (i == j) continue;
        		if (nums[i] + nums[j] == target) {
        			if (i < j) {
        				result[0] = i;
        				result[1] = j;
        			} else {
        				result[0] = j;
        				result[1] = i;
        			}
        			return result;
        		}
        	}
        }
        return result;
    }
    

    解题描述

    这道题目还是比较简单的,为了找到目标数字的下标,使用的是直接用双层循环遍历数组里面任意两个数的和,检查和是否等于给定的target。之后再返回存有所求的两个数字的下标的数组。

    更优解法

    2018.1.24 更新:

    之前这道题的做法属于暴力破解,时间复杂度还是较高的,达到了O(n^2),查了一些资料之后发现使用哈希可以把时间复杂度降到O(n):

    
    class Solution {
    public:
        vector<int> twoSum(vector<int>& nums, int target) {
            unordered_map<int, int> hash;
            int size = nums.size();
            vector<int> res(2);
            for (int i = 0; i < size; i++) {
                auto got = hash.find(target - nums[i]);
                if (got != hash.end()) {
                    res[0] = got -> second;
                    res[1] = i;
                    return res;
                }
                hash[nums[i]] = i;
            }
        }
    };
    

    3Sum 题解

    题目来源:https://leetcode.com/problems/3sum/description/

    Description

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

    Note: The solution set must not contain duplicate triplets.

    Example

    For example, given array S = [-1, 0, 1, 2, -1, -4],
    
    A solution set is:
    [
      [-1, 0, 1],
      [-1, -1, 2]
    ]
    

    Solution

    class Solution {
    private:
        vector<vector<int> > twoSum(vector<int>& nums, int end, int target) {
            vector<vector<int> > res;
            int low = 0;
            int high = end;
            while (low < high) {
                if (nums[low] + nums[high] == target) {
                    vector<int> sum(2);
                    sum[0] = nums[low++];
                    sum[1] = nums[high--];
                    res.push_back(sum);
    
                    // 去重
                    while (low < high && nums[low] == nums[low - 1])
                        low++;
                    while (low < high && nums[high] == nums[high + 1])
                        high--;
                } else if (nums[low] + nums[high] > target) {
                    high--;
                } else {
                    low++;
                }
            }
            return res;
        }
    public:
        vector<vector<int> > threeSum(vector<int>& nums) {
            vector<vector<int>> res;
            int size = nums.size();
            if (size < 3)
                return res;
            sort(nums.begin(), nums.end());
            for (int i = size - 1; i >= 2; i--) {
                if (i < size - 1 && nums[i] == nums[i + 1])  // 去重
                    continue;
                auto sum2 = twoSum(nums, i - 1, 0 - nums[i]);
                if (!sum2.empty()) {
                    for (auto& sum : sum2) {
                        sum.push_back(nums[i]);
                        res.push_back(sum);
                    }
                }
            }
            return res;
        }
    };
    

    解题描述

    这道题是Two Sum的进阶,解法上采用的是先求Two Sum再根据求到的sum再求三个数和为0的第三个数,不过题意要求不一样,Two Sum要求返回数组下标,这道题要求返回具体的数组元素。而如果使用与Two Sum相同的哈希法去做会比较麻烦。

    这里求符合要求的2数之和用的方法是,先将数组排序之后再进行夹逼的办法。并且为了去重,需要在2sum和3sum都进行去重。这样2sum夹逼时间复杂度为O(n),总的时间复杂度为O(n^2)。


    4Sum 题解

    题目来源:https://leetcode.com/problems/4sum/description/

    Description

    Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

    Note: The solution set must not contain duplicate quadruplets.

    Example

    For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0.
    
    A solution set is:
    [
      [-1,  0, 0, 1],
      [-2, -1, 1, 2],
      [-2,  0, 0, 2]
    ]
    

    Solution

    class Solution {
    private:
        vector<vector<int> > twoSum(vector<int>& nums, int end, int target) {
            vector<vector<int> > res;
            int low = 0;
            int high = end;
            while (low < high) {
                if (nums[low] + nums[high] == target) {
                    vector<int> sum(2);
                    sum[0] = nums[low++];
                    sum[1] = nums[high--];
                    res.push_back(sum);
    
                    // 去重
                    while (low < high && nums[low] == nums[low - 1])
                        low++;
                    while (low < high && nums[high] == nums[high + 1])
                        high--;
                } else if (nums[low] + nums[high] > target) {
                    high--;
                } else {
                    low++;
                }
            }
            return res;
        }
    
        vector<vector<int> > threeSum(vector<int>& nums, int end, int target) {
            vector<vector<int>> res;
            if (end < 2)
                return res;
            sort(nums.begin(), nums.end());
            for (int i = end; i >= 2; i--) {
                if (i < end && nums[i] == nums[i + 1])  // 去重
                    continue;
                auto sum2 = twoSum(nums, i - 1, target - nums[i]);
                if (!sum2.empty()) {
                    for (auto& sum : sum2) {
                        sum.push_back(nums[i]);
                        res.push_back(sum);
                    }
                }
            }
            return res;
        }
    public:
        vector<vector<int> > fourSum(vector<int>& nums, int target) {
            vector<vector<int>> res;
            int size = nums.size();
            if (size < 4)
                return res;
            sort(nums.begin(), nums.end());
            for (int i = size - 1; i >= 2; i--) {
                if (i < size - 1 && nums[i] == nums[i + 1])  // 去重
                    continue;
                auto sum3 = threeSum(nums, i - 1, target - nums[i]);
                if (!sum3.empty()) {
                    for (auto& sum : sum3) {
                        sum.push_back(nums[i]);
                        res.push_back(sum);
                    }
                }
            }
            return res;
        }
    };
    

    解题描述

    这道题可以说是3Sum的再次进阶,使用的方法和3Sum基本相同,只是在求3个数之和之后再套上一层循环。时间复杂度为O(n^3)。


    3Sum Closest 题解

    题目来源:https://leetcode.com/problems/3sum-closest/description/

    Description

    Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    Example

        For example, given array S = {-1 2 1 -4}, and target = 1.
    
        The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
    

    Solution

    class Solution {
    private:
        inline int abInt(int val) {
            return val >= 0 ? val : -val;
        }
    public:
        int threeSumClosest(vector<int>& nums, int target) {
            int size = nums.size();
            if (size < 3)
                return 0;
            sort(nums.begin(), nums.end());
            int closest = nums[0] + nums[1] + nums[2];
            int first, second, third, sum;
            for (first = 0; first < size - 2; ++first) {
                if (first > 0 && nums[first] == nums[first - 1])
                    continue; // 去重
                second = first + 1;
                third = size - 1;
                while (second < third) {
                    sum = nums[first] + nums[second] + nums[third];
                    if (sum == target)
                        return sum;
                    if (abInt(sum - target) < abInt(closest - target))
                        closest = sum;
                    if (sum < target)
                        ++second;
                    else
                        --third;
                }
            }
            return closest;
        }
    };
    

    解题描述

    这道题可以说是3Sum的变形,题意上是要求在数组里面找到三个数的和最接近target,也就是说可能不等于target。算法上面与3Sum的解法有一定的相似度,先固定一个位置first,在其后进行夹逼求最接近target的三数之和。

  • 相关阅读:
    矩阵旋转
    clang-format 规范及 Visual Stido Code 自定义格式化代码风格
    Windows 安装 MinGW-w64
    Linux配置Visual Stdio Code
    Ubuntu中安装eclipse
    Ubuntu安装JDK11
    Ubuntu安装搜狗输入法
    C/C++算术运算(类型使用)的注意事项
    闰年判断与日期计算
    查看变量类型
  • 原文地址:https://www.cnblogs.com/yanhewu/p/8482751.html
Copyright © 2020-2023  润新知