【leetcode】兩數相加(演算法)
阿新 • • 發佈:2018-11-06
兩數之和
給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。
你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。
看到題目我首先想到的是將目標值(target)拆分,將目標值變成0+target,1+(target-1),...,(target/2)+(target-target/2).
由於第一次做演算法題,我這種思想在我剛準備打程式碼時就直接被我拋之腦後,因為這種思路其實很'暴力',陣列可能根本沒有這麼多數,如果給定的target很大,那我勢必會在拆分上花費很大的開銷。
那麼現在,我們可以改進,得到的是,直接用target減去數組裡的數,用得到的數去從數組裡找,這樣的話我們就節省很多。這是又有一個小問題,如果你從數組裡找,你每減一個數,你勢必需要遍歷一遍陣列。而我是將target減過的數放進List裡面,從後面找前面已有的數。
程式碼如下:
class Solution { public int[] twoSum(int[] nums, int target) { List list =new ArrayList<Integer>(); int result[] = new int[2]; for (int i = 0 ;i<nums.length;i ++){ if (list.contains(target-nums[i])) { result[0]=list.indexOf(target-nums[i]); result[1]=i; break; }else { list.add(nums[i]); } } return result; } }
時間複雜度為O(n),執行的時間大概為幾十ms,下面則是幾ms的程式碼;
class Solution { public int[] twoSum(int[] nums, int target) { // 先複製一份陣列 int[] newNums = Arrays.copyOf(nums, nums.length); // 排序複製的陣列 Arrays.sort(newNums); // 結果集 int[] res = new int[2]; // 迴圈遍歷每一個 for (int i=0; i<newNums.length - 1; i++) { // 如果剩餘的數只有一個,那麼判斷這一個,並退出迴圈 if (newNums.length-i-1 == 1) { if (newNums[i]+newNums[i+1] == target) { res = new int[]{i,i+1}; } else { res = null; } break; } // 如果剩餘的不只一個,則用二分法 int num = newNums[i]; int rest = target-num; int start = i+1; int end = newNums.length-1; int mid; // = (start+end) / 2; int src = -1; while(start < end) { mid = (start+end+1) / 2; if (rest < newNums[mid]) { end = mid-1; } else if (rest > newNums[mid]) { start = mid+1; } else { src = mid; break; } } if (start == end && newNums[start] == rest) { src = start; } // 如果二分法找到,則退出迴圈 if (src != -1) { res[0] = i; res[1] = src; break; } } boolean flag1=false; boolean flag2=false; // 在原陣列中查詢位置 for(int i=0; i<nums.length; i++) { if (flag1 && flag2) break; if (!flag1 && nums[i] == newNums[res[0]]) { res[0] = i; flag1 = true; continue; } if (!flag2 && nums[i] == newNums[res[1]]) { res[1] = i; flag2 = true; } } return res; } }