[Chinese ver]1.兩數求和 。給定一個整數的數組,返回兩個數字的索引使得這兩個數字加起來成爲一個指定的目標值。
你能夠假設每一個輸入都至少有一個解決方案,而且你不能使用相同的元素兩次。java
Example:git
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].複製代碼
首先是一次錯誤的嘗試github
public class Solution {
public int[] twoSum(int[] nums, int target) {
int[] testNums = new int[nums.length];
int j = 0;
for (int i=0;i<nums.length;i++){
if(nums[i]<target){
testNums[j] = nums[i];
j=j+1;
}
}
for(int l=0;l<j;l++){
for(int k=l+1;k<j;k++){
if(testNums[l]+testNums[k]==target){
return new int[]{l,k};
}
}
}
return null;
}
}複製代碼
沒理解好題意,這種解法最後獲得的是咱們自定義數組的序號,而不是題目要求的序號,暈倒。。。後來發現一個更嚴重的問題。。他沒有說過不能有負數!!!!也就不須要判斷數組裏的值是否大於和。。。數組
而後從新構思一下,先來個基本的解法bash
public class Solution {
public int[] twoSum(int[] nums, int target) {
for (int i=0;i<nums.length;i++){
for(int k=i+1;k<nums.length;k++){
if(nums[i]+nums[k]==target){
return new int[]{i,k};
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
}複製代碼
至於結果嘛,最簡單的天然也高效不到哪裏。
ui
分析
這個方法的原理很簡單,就是將每個值與其餘的值循環遍歷,看是否有符合條件的狀況發生。稍微要注意的是 for(int k=i+1;k<nums.length;k++) 這裏k=i+1是爲了不前面循環過的狀況再次循環一遍。
時間複雜度 : O(n^2) 。n個元素都要循環遍歷數組內其他的元素,因此是n^2。
空間複雜度 : O(1) .spa
public class Solution {
public int[] twoSum(int[] numbers, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < numbers.length; i++) {
map.put(numbers[i],i);
}
for (int i = 0; i < numbers.length; i++) {
int requestNum = target - numbers[i];
if (map.containsKey(requestNum)&&map.get(requestNum)!=i) {
return new int[]{i,map.get(requestNum)};
}
}
throw new IllegalArgumentException("No two sum solution");
}
}複製代碼
能夠看到效率有了很大的提高。3d
分析
這個方法的原理其實就是使用hash table 來將時間成原本替換空間成本,將一次複雜度爲O(n)的循環變爲接近O(1)的查找,爲何是接近呢,由於若是hash table發生大量的碰撞,就會致使複雜度向O(n)靠近。咱們將數組裏每個元素的值做爲key存入hash table,而將其序列號做爲對應的value存入hash table,而後遍歷數組查找是否有對應的值在hash table 的key中,有則取出該key對應的value。
時間複雜度 : O(n)
空間複雜度 : O(n)code
public class Solution {
public int[] twoSum(int[] numbers, int target) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < numbers.length; i++) {
int requestNum = target - numbers[i];
if (map.containsKey(requestNum)) {
return new int[]{map.get(requestNum),i};
}
map.put(numbers[i],i);
}
throw new IllegalArgumentException("No two sum solution");
}
}複製代碼
效率稍微提升了一些。。可是有些不能接受啊。怎麼還只是在中間的位置。。。而後試了幾回,大概在40%到50%徘徊,前面那些是用什麼算的。。。爲什麼那麼快。理論上來講至少須要循環比對結果一次,也就是須要O(n)的複雜度。cdn
分析
這個方法的原理其實就是方法二的一個改善,由於咱們不須要將所有的數組都放入hash table ,咱們最終的目的是爲了獲得兩個相加等於目標數的值的序號便可,因此咱們在將數組裏的值放入hash table 的時候就進行比對,一旦獲得所須要的值當即結束循環。
時間複雜度 : O(n)
空間複雜度 : O(n)
若是你有更好的辦法或者對我這裏的描述有其餘見解,請聯繫我。謝謝