LeetCode167. Two Sum II - Input array is sorted

一、問題描述

Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.

Note:

  • Your returned answers (both index1 and index2) are not zero-based.
  • You may assume that each input would have exactly one solution and you may not use the same element twice.

Example:

Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.

注意事項:返回的是索引,不是下標。

二、解題思路

其實,如果2 Sum和3 Sum的問題搞定了,這道題真的很easy。就是left和right的移動問題

三、代碼實現(類似於快速排序)

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        unordered_map<int,int> result;
        vector<int> vec;
        int left = 0;
        int right = numbers.size()-1;
        while(left < right){
            int sum = numbers[left] + numbers[right];
            if(sum > target){
                right--;
            } else if(sum < target){
                left++;
            } else {
                //題目要求,索引下標加1了
                vec.push_back(left+1);
                vec.push_back(right+1);
                left++;
                right--;
            }
        }
        return vec;
    }
};

四、這道題的變種

1. 如果有多對數字的和等於target,輸出兩個數的乘積最小的。

#include <climits>
class Solution
{
public:
    vector<int> FindNumbersWithSum(vector<int> a,int sum)
    {
        if(a.size()<2) return vector<int>();
       
        int min_product = INT_MAX;
        int left = 0, 
        right = a.size()-1;
        int a1,a2;
        bool find_flag = false;
        while(left < right) //從兩邊開始往中間掃描
        {
            int cursum = a[left] + a[right];
            if(cursum > sum) right--;
            else if(cursum < sum) left++;
            else
            {
                //因爲對於遞增序列,一定有x*y < (x+a)*(y-a),故這裏其實可以不用判斷
                //從兩邊開始往中間掃描時,找到的第一個即爲乘機最小的一對數
                if(a[left]*a[right] < min_product)
                {
                    find_flag = true;
                    min_product = a[left]*a[right];
                    a1 = a[left];
                    a2 = a[right];
                }
                left++; //繼續掃描
            }
        }
        if(find_flag) return vector<int>{a1,a2};
        else return vector<int>();
       
    }
};

2. 和爲sum的連續正數序列(至少包括兩個數,例如:100:[9,10,11,12,13,14,15,16]/[18,19,20,21,22]...)

class Solution
{
public:
    vector<vector<int> > FindContinuousSequence(int sum)
    {
        vector<vector<int>> result;
        if(sum < 3) return result; //至少需包含兩個數 
       
        int left = 1, right = 2; //序列從1開始
        while(left < right) //注意從開頭開始掃描,直到left與right相遇
        {
            int cursum = (left+right)*(right - left + 1)/2; //用等差數列的求和公式
            if(cursum < sum) right++;
            else if(cursum > sum) left++;
            else
            {
                vector<int> temp;
                for(int i = left; i <= right; i++)
                    temp.push_back(i);
                result.push_back(temp); //push符合要求的連續正數序列,不止一組
                left++; //繼續下個序列的尋找
            }
        }
        return result;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章