LeetCode | Two Sum

Given an array of integers, 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. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

要求:返回的index值不能直接是數組下標,nums[0]的index爲1,且index[0]<index[1]

//基本的brute force方法,可以accept,時間複雜度爲O(n^2)
//題目tag提示HashTbale,顯然此方法不推薦
public class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] index = new int[2];
        for(int i=0; i<nums.length; i++){
            int num_1 = nums[i];
            for(int j=i+1; j<nums.length; j++){
                int num_2 = nums[j];
                if(num_1+num_2 == target){
                    index[0] = i+1;
                    index[1] = j+1;
                    return index;
                }
            }
        }
        return index;
    }
}


//用HashMap:
//向後遍歷,遍歷過的元素作爲備選集合,對每一個元素nums[i],需要找到needNum=target-nums[i]
//如果能在備選集中找到needNum,那麼index=[index_needNum+1, i+1],否則就把nums[i]也加入備選集
//注意一點:要先確認needNum在備選集中找不到,才能把nums[i]加入備選集。否則如[3,2,4],target=6
//先把3加入備選集,再來找needNum,都不會向後遍歷,直接返回[1,1]了
public class Solution {
    public int[] twoSum(int[] nums, int target) {
        
        int[] index = new int[2];
        HashMap<Integer, Integer> myMap = new HashMap<Integer, Integer>();
        
        for(int i=0; i<nums.length; i++){
            int needNum = target - nums[i];
            //myMap.put(nums[i], i);             //put語句不能放在此處,如果target恰爲2*nums[i]
            if(myMap.containsKey(needNum)){       //那它只要自己加自己就等於target,就會return [i,i]
                index[0] = myMap.get(needNum) + 1;
                index[1] = i + 1;
                return index;
            }
            myMap.put(nums[i], i);
        }
        
        return index;
    }
}

此外,如果不是要求返回兩個元素的index,而是直接返回兩個元素,那麼也可以用如下形式:

(2015.6.28補充:不要用list或其他容器來維護已便利過的數組,用hashmap,因爲其他容器的contains方法比map的contains要慢的多)

(map的contains是直接用key的hash值來計算,再判斷的,非常之快。而其他容器如list可能也是通過遍歷來確定是否contains的,故而很慢)

//不返回index,而是返回和爲target的數
//就無需利用map來額外維護index,只需一個允許重複且擁有contains()方法的容器即可
public class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        List<Integer> myList = new ArrayList<Integer>();
        
        for(int i=0; i<nums.length; i++){
            int needNum = target - nums[i];
            if(myList.contains(needNum)){
                result[0] = needNum;
                result[1] = nums[i];
                return result;
            }else{
                myList.add(nums[i]);
            }
        }
        
        return result;
    }
}

或者先排序,再用二分法:

        Arrays.sort(nums);      //注意:排序後元素的index已經被打亂了
        for(int i=0; i<nums.length; i++){
            int tempNum = nums[i];
            int needNum = target - tempNum;
            
            //開始用二分查找,確認needNum的位置
            int head = i+1;
            int tail = nums.length - 1;
            
            while(head <= tail){
                int middle = (head + tail) / 2;
                if(nums[middle] == needNum){
                    result[0] = nums[1];
                    result[1] = nums[middle];
                    return result;
                }else if(nums[middle] > needNum){
                    tail = middle - 1;
                }else if(nums[middle] < needNum){
                    head = middle + 1;
                }
            }
        }

爲了進一步降低算法的時間複雜度,對twoSum繼續優化。上面只是優化到引入二分查找就沒再繼續了。

但若用夾逼的思想,則除去排序的O(nlogn)外,只需一次遍歷O(n)就一定可以找到一對sum爲target的兩個值(此處假設nums中只有一對滿足要求),代碼如下:

    Arrays.sort(nums);             //先對數組進行排序
    int left = 0;
    int right = nums.length - 1;
    while(left < right){
    	if(nums[left]+nums[right] == target){
    		return new int[]{nums[left], nums[right]};
    	}else if(nums[left]+nums[right] > target){
    		right--;
    	}else if(nums[left]+nums[right] < target){
    		left++;
    	}
    }


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