一、什么是雙指針
雙指針我所理解地是在遍歷對象時,不是使用單個指針進行訪問,而是使用兩個相同方向或者相反方向的指針進行遍歷,從而達到相應的目的。
在JAVA中並沒有像C/C++指針地概念,所以這里所說的雙指針是指索引,游標或可迭代對象等。
雙指針在鏈表中也有很多用處,比如前面寫到過的找出鏈表中的倒數第k個結點,就巧妙地利用到了雙指針,此外,判斷鏈表中是否有環也可以使用雙指針,設兩個快慢指針,讓快指針一次移動兩步,慢指針一次移動一步,若鏈表中有環,那么快指針與慢指針一定能夠相遇,若兩者沒有相遇,說明鏈表中沒有環。還有如果要給出鏈表中的中間的結點,也可以使用快慢指針,讓快指針一次移動兩步,慢指針一次移動一步,當快指針剛好到達鏈表的末尾時,慢指針所指向的正好是中間的結點(對於奇數個結點,就是中間中的一個,若是偶數個結點,是中間結點中的后一個,即length / 2);
由此看出,雙指針的思想就是建立兩個指針,這兩個指針可以使相同方向,一般前進的速度不同或者兩者的前進順序不一致;也可能是相反的方向,通過使用相關的變量控制來達到我們的目的。
二、例子:
給定一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重復的三元組。
注意:答案中不可以包含重復的三元組。
例如, 給定數組 nums = [-1, 0, 1, 2, -1, -4],
滿足要求的三元組集合為:
[
[-1, 0, 1],
[-1, -1, 2]
]
1.思路:
- 將數組進行排序。
- 將三數問題轉換成兩數問題(構建for循環)。
- 對於兩數問題使用雙指針求解。
2.代碼
public List<List<Integer>> threeSum(int[] nums) { Arrays.sort(nums); List<List<Integer>> ls = new ArrayList<>(); for (int i = 0; i < nums.length - 2; i++) { if (i == 0 || (i > 0 && nums[i] != nums[i - 1])) { // 跳過可能重復的答案 int l = i + 1, r = nums.length - 1, sum = 0 - nums[i]; while (l < r) { if (nums[l] + nums[r] == sum) { ls.add(Arrays.asList(nums[i], nums[l], nums[r])); while (l < r && nums[l] == nums[l + 1]) l++; while (l < r && nums[r] == nums[r - 1]) r--; l++; r--; } else if (nums[l] + nums[r] < sum) { while (l < r && nums[l] == nums[l + 1]) l++; // 跳過重復值 l++; } else { while (l < r && nums[r] == nums[r - 1]) r--; r--; } } } } return ls; }