和为S的两个数

时间:2023-12-28 16:03:02

题目

输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

输出描述:

对应每个测试案例,输出两个数,小的先输出。

思考

  • 注意题目的条件:有序数组
    • 对于此题的条件,我们可以将 有序 的条件充分利用起来,是用双向指针解决
  • 扩展,对于一般的无序数组:
    • 是用 hash 表减小查找的复杂度,空间换时间,时间复杂度为 O(n)
    • 可以先将数组排序然后是用双向指针求解,时间复杂度依赖于排序算法,因此最好的情况为 O(nlog(n))

code


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
#include <limits>

using namespace std;

class Solution{
public:
    vector<int> FindNumbersWithSum(vector<int> array, int sum){
        //return FindNumbersWithSumHash(array, sum);
        return FindNumbersWithSumSortedArray(array, sum);
    }

    // time-O(n), space-O(1)
    // Note: the array must be sorted array.
    vector<int> FindNumbersWithSumSortedArray(vector<int> array, int sum){

        int left = 0, right = array.size()-1;
        long long minimum = numeric_limits<int>::max();
        int cond1, cond2;
        while(left < right){
            int curSum = array[left] + array[right];
            if(curSum > sum)
                right--;
            if(curSum < sum)
                left++;
            if(curSum == sum){
                long long mul = array[left] * array[right];
                if(mul < minimum){
                    minimum = mul;
                    cond1 = array[left];
                    cond2 = array[right];
                }
                left++; // note: escape the duplication to avoid the infinite loop
            }
        }

        if(minimum == numeric_limits<int>::max()){
            return vector<int>();
        }else{
            vector<int> ans(2);
            ans[0] = cond1;
            ans[1] = cond2;
            return ans;
        }
    }

    // time-O(n) , space-O(n)
    vector<int> FindNumbersWithSumHash(vector<int> array, int sum){
        unordered_set<int> setNums;
        long long minimum = numeric_limits<long long>::max();
        int cond1, cond2;
        for(int n : array){
            int another = sum - n;
            if(setNums.find(another) != setNums.end()){
                if(another * n < minimum){
                    cond1 = n;
                    cond2 = another;
                    minimum = another*n;
                }
            }
            setNums.insert(n);
        }

        if(minimum == numeric_limits<long long>::max()){
            return vector<int>();
        }else{
            if(cond2 < cond1)
                swap(cond1, cond2);
            vector<int> ans(2);
            ans[0] = cond1;
            ans[1] = cond2;
            return ans;
        }

    }
};

int main()
{
    return 0;
}