LeetCode第[1]題(Java):Two Sum (倆數和為目標數的下標)——EASY


題目:

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.

翻譯:

給定一組整數,兩個數字的返回索引,它們的和會等於一個特定的數。

您可能假設每個輸入都有一個解決方案,但是你不能使用同一個元素兩次。(好吧一開始英語弱雞的我也沒懂,后來編程的時候想到的解釋:同一個數不能通過自加而得到目標數

第一遍編寫:74ms

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Set<Integer> resultSet = new HashSet<Integer>();
        for (int i = 0; i < nums.length; i++) {
            for (int j = i + 1; j < nums.length; j++) { // 就是這里想到一個數自加,所以應該從i+1開始。
                if (nums[i] + nums[j] == target) {
                    resultSet.add(i);
                    resultSet.add(j);
                }
            }
        }
        int[] result = new int[resultSet.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = (Integer) resultSet.toArray()[i];
        }
        return result;
    }
}

好吧,第一次刷題,隱隱小激動,一開始確實沒看清題目。。

 

看清題目后第一次:46ms    時間復雜度:O(n2)

 1 class Solution {
 2     public int[] twoSum(int[] nums, int target) {
 3         int[] result = new int[2];
 4         for (int i = 0; i < nums.length; i++) {
 5             for (int j = i + 1; j < nums.length; j++) {
 6                 if (nums[i] + nums[j] == target) {
 7                     result[0] = i;
 8                     result[1] = j;
 9                     break;
10                 }
11             }
12         }
13         return result;
14     }
15 }

自己看着都覺得菜的很。。竟然用了嵌套for。。

 

 下面是參考答案:12ms    時間復雜度:O(n)

 1     public int[] twoSum(int[] nums, int target) {
 2         Map<Integer, Integer> map = new HashMap<Integer, Integer>();
 3         int[] result = new int[2];
 4         
 5         for (int i = 0; i < nums.length; i++) {
 6             if (map.containsKey(target - nums[i])) {
 7                 result[0] = map.get(target - nums[i]);
 8                 result[1] = i;  // 此時 i 對應的元素還沒有放進去。
 9                 return result;
10             }
11             map.put(nums[i], i);
12         }
13         return result;
14     }

原來用了HashMap來定位兩者有某種關系的數。。快了一倍多。。

 結論:

當需要使用嵌套for循環來查找或者定位的時候,盡量優先考慮是否能使用Map(存儲每一個值作為key,相應下標作為value)

使用  map.containsKey(__) 方法來進行定位

2018-1-8更新:今天做到3sum想到和這里的2sum聯系,

3sum:求所有的相加為目標值的數組

2sum:一旦查找到相加為目標值的倆數組則直接返回倆下標,程序直接結束(僅一組

現在將2sum的題目改為如下:

給定一個n個整數的數組,在數組中找到和為目標值的所有唯一的兩個元素組合【注意不是求下標】

注意:答案集不能包含重復的雙胞胎。

測試用例:{1,4,-1,2,-1,0}   1     結果:[[0, 1], [-1, 2]]

     {3,2,3,4,1,4,5,5}  8     結果:[[4, 4], [3, 5]]

 

Code1:時間復雜度:O(N)    【其實應該是Arrays.sort(num)的復雜度】

 1     public static List<List<Integer>> twoSumAll(int[] num, int target) {
 2         Arrays.sort(num);                            // 將所有相同元素挨在一起
 3         List<List<Integer>> res = new LinkedList<List<Integer>>();
 4         Set<Integer> set = new HashSet<Integer>();  // 不需要下標,並且需要元素唯一,所以采用Set
 5         for (int i = 0; i < num.length; i++) {
 6             if (set.contains(target - num[i])) {
 7                 res.add(Arrays.asList(target - num[i], num[i]));
 8                 set.remove(target - num[i]);        // 防止后續重復元素繼續利用此值(因為已經排序,后面不會再有前面的值,不需要再remove(num[i]))
 9             }
10             set.add(num[i]);
11         }
12         return res;
13     }

此方法仍然采用上面2sum的思想,利用contains()函數減少一次循環,注意Set的remove使答案避免了”雙胞胎數組“

下面采用第15題的3sum的‘雙指針相向移動‘’的思想進行算法編寫:

Code2:時間復雜度:O(N)   【其實應該是Arrays.sort(num)的復雜度】

 1     public static List<List<Integer>> twoSumAll2(int[] num, int target) {
 2         Arrays.sort(num);                            
 3         List<List<Integer>> res = new LinkedList<List<Integer>>();
 4         int left = 0;
 5         int right = num.length - 1;
 6         while (left < right) {
 7             if (num[left] + num[right] == target) {
 8                 res.add(Arrays.asList(num[left], num[right]));
 9                 while (left < right && num[left] == num[left+1]) left++;
10                 while (left < right && num[right] == num[right-1]) right--;
11                 left++;
12                 right--;
13             } else if (num[left] + num[right] < target) {
14                 left++;
15             } else {
16                 right--;
17             }
18         }
19         return res;
20     }

雙指針相向移動:利用了  已排序數組  和  所查找的兩個數的和為定值  這兩個性質

        這兩個性質如果聯合一起用的話………………duang!!!

        在已排序數組兩端指針所指數之和如果小於目標值,只需要移動左邊的指針,否則只需要移動右邊的指針

        【還看不懂可以自己打草稿試試,或者看我這個博客:LeetCode第[15]題(Java):3Sum 標簽:Array

結論:在求和為目標數時,求下標——HashMap;

            求具體組合值——前后指針;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM