前端工作筆記(一)
阿新 • • 發佈:2022-05-16
雙指標解決NSum問題
1.兩數之和
public int[] twoSum(int[] nums, int target) { /** * 首先,對於該題要求返回原始陣列下標,這裡就要求不能手動排序 * 所以二分的思路行不通, * 但是這裡可以使用雜湊表,降低時間複雜度。使用雜湊表時,由於雜湊表剛開始並沒有建立啊 * */ Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int need = target - nums[i]; if (map.containsKey(need)){ return new int[]{i, map.get(need)}; } map.put(nums[i], i); } return null; }
此時表不能進行排序。因為人家要求返回原始陣列下標。
這裡剛開始遍歷時,雜湊表裡並沒有資料,但是如果前面某個數事最後要返回的那個數字,在後面遍歷的時候一定會和前面的資料配對,也就是說雜湊表裡這時候有資料了。
2.三數之和
[-1,0,1,2,-1,-4]
排序之後是:
[-4, -1, -1, 0, 1, 2]
分析:依次選取第一個第二個數,
- 對於第一個數來說,不能選取重複的,因為選取了第一個數為-1,第二次再以-1作為第一個數的話,第二個數得到的結果一定是第一個-1得到的結果的子集。
- 對於第2個數來說,第二個數也不能相同,這樣得到的一定是相同的結果集。
class Solution {
public List<List
//首先是排序為有序陣列
Arrays.sort(nums);
int n = nums.length;
//存放最終結果
List<List
for (int i = 0; i < n; i++) { //對於選取的第一個數字 if (i > 0 && nums[i] == nums[i - 1]) { continue; } //每一輪開始的條件: int j = i + 1; int k = n - 1; while (j < k) { //能夠提前判斷並且結束 while (j > i + 1 && j < n && nums[j] == nums[j - 1]){ j++; } if (j >= k) { break; } int sum = nums[i] + nums[j] + nums[k]; if (sum == 0){ //注意新增結果集的操作,新增之後,還是要判斷更新j的值 ans.add(Arrays.asList(nums[i], nums[j], nums[k])); j++; }else if (sum > 0){ k--; }else if (sum < 0){ j++; } } } return ans; }
}
- 最接近的三數之和
public int threeSumClosest(int[] nums, int target) {
/**
* 為了找到最接近target的三數之和,必須要使用取絕對值函式,但是這裡要謹記,
* 對於初始值應該讓其初始化為陣列中的元素之和,不能隨意的初始化。
*/
Arrays.sort(nums);
int n = nums.length;
int res = nums[0] + nums[1] + nums[2];
for (int i = 0; i < n; i++) {
if (i > 0 && nums[i] == nums[i - 1]){
continue;
}
int j = i + 1;
int k = n - 1;
while (j < k){
if (j > i + 1 && j < n && nums[j] == nums[j - 1]){
j++;
}
if (j >= k){
break;
}
int sum = nums[i] + nums[j] + nums[k];
// res = Math.min(Math.abs(target - sum), res);
res = Math.abs(sum - target) < Math.abs(res -target) ? sum : res;
// if(Math.abs(sum - target) < Math.abs(res - target)){
// res = sum;
// }
if (sum == target){
return sum;
}else if (sum > target){
k--;
}else if (sum < target){
j++;
}
}
}
return res;
}
18.四數之和
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> res = new ArrayList<>();
int n = nums.length;
for (int i = 0; i < n; i++) {
//控制第一個數
if (i > 0 && nums[i] == nums[i - 1]){
continue;
}
//控制第二個數
for (int j = i + 1; j < n; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]){
continue;
}
int k = j + 1;
int p = n - 1;
while (k < p){
while (k > j + 1 && k < n && nums[k] == nums[k - 1]){
k++;
}
while (k >= n){
break;
}
//這裡是因為leecode給出的測試案例太大,溢位,最好轉為long型別
long sum = (long) nums[i] + nums[j] + nums[k] + nums[p];
if (sum == target){
res.add(Arrays.asList(nums[i], nums[j], nums[k], nums[p]));
k++;
}
else if (sum > target){
p--;
} else if (sum < target) {
k++;
}
}
}
}
return res;
}
這樣對於NSum問題來說就有一個很好的解決方法:
直接使用3Sum作為迭代終點,其他的依次呼叫(n-1)Sum即可