1. 程式人生 > >演算法習題篇之Twosum

演算法習題篇之Twosum

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.

不到英語四級的水平隨便翻譯一下,以後的不再詳細說明

 給一個integer 型別的陣列,返回其中兩個數的索引,這兩個數的和等於target。

你可以認為每一個輸入只有一個答案,所以你不能用其中的一個元素兩次

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

我的思路很簡單,不就是兩兩配對不重複嘛,就寫了兩個for迴圈,然後解決了問題,我的程式碼如下:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        for(int i = 0 ;i<nums.length;i++){
            for(int j = i+1;j<nums.length;j++){
                if(nums[i]+nums[j]==target){
                    int[] twoSum = {i,j};
                    return twoSum;
                }
            
            }
        }
        return null;
    }
}

當然了,瑕疵多的不要不要的,來一發和我一樣思路的,比較正規的答案:

public int[] twoSum(int[] nums, int target) {
    for (int i = 0; i < nums.length; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[j] == target - nums[i]) {
                return new int[] { i, j };
            }
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}
  • Time complexity : O(n2). For each element, we try to find its complement by looping through the rest of array which takes O(n) time. Therefore, the time complexity is O(n2)

  • Space complexity : O(1). 

  • 時間複雜度是n的二次方了,空間複雜度就是一了,

記得好像是算術表示式什麼的最後放在右邊,效率會有所提高,至於throw不throw的話,應該是沒有什麼事情的了。

接下來呢,就是乾貨了,當然是以我現在小白的水平沒有想到的東西了:

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        map.put(nums[i], i);
    }
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement) && map.get(complement) != i) {
            return new int[] { i, map.get(complement) };
        }
    }
    throw new IllegalArgumentException("No two sum solution");
}

當然看上去,其實所有的東西我們都會了,但是為什麼寫的時候用不出來呢,當然是因為用的少了,先把整個陣列的索引和值放到一個map集合中,然後就是迴圈能不能找到和自己配對的另一個map了,當然這裡最重要的是這個map.containsKey這個函式的時間複雜度是多少,作者去查了一下https://blog.csdn.net/qq_36442947/article/details/81903542是1到n了,那個value的話就肯定是n的。另一個比較詳細的分析https://blog.csdn.net/qingtian_1993/article/details/80763381

  • Time complexity : O(n). We traverse the list containing nn elements exactly twice. Since the hash table reduces the look up time to O(1)O(1), the time complexity is O(n).

  • Space complexity : O(n) The extra space required depends on the number of items stored in the hash table, which stores exactly nn elements. 

  • 這裡一臉懵逼的表示為什麼時間複雜度就變成n了呢,最壞的情況去哪裡了,真的是一臉懵逼,不過這不耽誤我們去使用它,這個的確比上一個方法效率更高,但是相應的,他的空間複雜度也變成了n,所以有舍才有得。

下一個就是這個的改進版了。

public int[] twoSum(int[] nums, int target) {
    Map<Integer, Integer> map = new HashMap<>();
    for (int i = 0; i < nums.length; i++) {
        int complement = target - nums[i];
        if (map.containsKey(complement)) {
            return new int[] { map.get(complement), i };
        }
        map.put(nums[i], i);
    }
    throw new IllegalArgumentException("No two sum solution");

這個就是判斷新來的值有沒有map裡的值和他配對的,如果沒有就放到集合裡了。

Complexity Analysis:

  • Time complexity : O(n)O(n). We traverse the list containing nn elements only once. Each look up in the table costs only O(1)O(1) time.

  • Space complexity : O(n)O(n). The extra space required depends on the number of items stored in the hash table, which stores at most nn elements.

我的確也想過提高效率的方法,但是我想的方法就有點小兒科了,如果外層迴圈得到的第一個值是大於target的就放掉了。

相同的這個map的方法就是說,如果是大於target 的就不往map集合裡邊放了,但是hehe,要是有負數怎麼辦,好了,這個很簡單的題就分析到這裡了。