演算法習題篇之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,要是有負數怎麼辦,好了,這個很簡單的題就分析到這裡了。