雙指針
- 兩數之和(有序數組,相向雙指針)
- 問題:在有序數組中找到兩個數,使它們的和等于目標值。
- 思路:左指針從起點出發,右指針從終點出發,根據和與目標值的大小調整指針。
#include <vector>
using namespace std;vector<int> twoSum(vector<int>& numbers, int target) {int left = 0; // 左指針(起點)int right = numbers.size() - 1; // 右指針(終點)while (left < right) {int sum = numbers[left] + numbers[right];if (sum == target) {// 找到目標,返回索引(題目可能要求+1,根據具體要求調整)return {left + 1, right + 1};} else if (sum < target) {// 和太小,左指針右移(增大總和)left++;} else {// 和太大,右指針左移(減小總和)right--;}}return {}; // 無結果(題目通常保證有解)
}
移動零
- 思路:左指針從起點出發,右指針也從起點出發,但是快慢不同。
class Solution { // 定義Solution類,用于封裝解題方法
public: // 公共成員函數,外部可直接調用// 函數定義:接收整數數組nums的引用(原地修改),無返回值void moveZeroes(vector<int>& nums) {int l = 0; // 定義慢指針l,初始化為0// 作用:記錄下一個非零元素應該存放的位置int n = nums.size(); // 計算數組長度n,避免多次調用size()函數// 定義快指針r,從0開始遍歷整個數組for(int r = 0; r < n; r++){// 當快指針指向的元素不是0時if(nums[r] != 0){// 將非零元素放到慢指針l的位置nums[l] = nums[r];// 慢指針后移一位,準備接收下一個非零元素l++;}}// 遍歷結束后,慢指針l之前的位置已放滿所有非零元素// 從l開始到數組末尾,填充0for(int i = l; i < n; i++){nums[i] = 0;}}
};
盛最多水的容器
class Solution { // 定義Solution類,用于封裝解題方法
public: // 公共成員函數,外部可直接調用// 函數定義:接收整數數組height的引用,返回最大容器容量(整數)int maxArea(vector<int>& height) {// 初始化雙指針:left指向數組起點,right指向數組終點int left = 0, right = height.size() - 1;// 初始化最大容量為0,用于記錄遍歷過程中找到的最大容量int maxWater = 0;// 雙指針循環條件:當左指針在右指針左側時繼續遍歷while (left < right) {// 計算當前容器的高度:取左右指針所指高度的較小值(容器高度由矮邊決定)int h = min(height[left], height[right]);// 計算當前容器的寬度:左右指針之間的距離(下標差)int w = right - left;// 更新最大容量:取當前容量(h*w)和歷史最大容量的較大值maxWater = max(maxWater, h * w);// 指針移動策略:移動較矮一側的指針(嘗試尋找更高的邊以增加容量)if (height[left] < height[right]) {left++; // 左指針較矮,右移左指針} else {right--; // 右指針較矮(或等高),左移右指針}}// 循環結束后,返回最大容量return maxWater;}
};
三數之和
#include <vector> // 引入vector容器頭文件,用于存儲動態數組
#include <algorithm> // 引入algorithm頭文件,用于調用sort排序函數
using namespace std; // 使用std命名空間,簡化代碼書寫class Solution { // 定義Solution類,封裝解題方法
public: // 公共成員函數,外部可直接調用// 函數定義:接收整數數組nums,返回所有和為0的三元組(不重復)vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>> res; // 定義結果容器,存儲符合條件的三元組sort(nums.begin(), nums.end()); // 對數組排序:1.便于雙指針查找 2.便于去重int n = nums.size(); // 計算數組長度n,避免重復調用size()// 外層循環:固定三元組中的第一個元素nums[i]for (int i = 0; i < n; ++i) {// 去重:若當前元素與前一個元素相同,跳過(避免重復三元組)if (i > 0 && nums[i] == nums[i - 1]) continue;// 定義雙指針:left指向i的下一個元素,right指向數組末尾int left = i + 1, right = n - 1;// 雙指針循環:尋找與nums[i]之和為0的兩個元素while (left < right) {// 計算當前三元組的和int sum = nums[i] + nums[left] + nums[right];if (sum == 0) { // 找到和為0的三元組// 將三元組加入結果容器res.push_back({nums[i], nums[left], nums[right]});// 去重:跳過left指針的重復元素while (left < right && nums[left] == nums[left + 1]) left++;// 去重:跳過right指針的重復元素while (left < right && nums[right] == nums[right - 1]) right--;// 雙指針同時移動,繼續尋找新的可能組合left++;right--;} else if (sum < 0) { // 和小于0,需增大總和(左指針右移)left++;} else { // 和大于0,需減小總和(右指針左移)right--;}}}return res; // 返回所有符合條件的三元組}
};
接雨水
這個題目的關鍵是看每兩個柱子之間的高度差,而不是相乘求面積!因為其中的數值有變化嗎,如果按照求面積與盛水容器一樣的方法就會導致多求!算錯這是我的錯誤是思路!
但其相同點依舊是從左右指針開始判斷大小。
int left = 0;int right = height.size() - 1;// 當左指針在右指針左側時,繼續遍歷(兩指針相遇則遍歷結束)while (left < right) {......}
class Solution {
public:int trap(vector<int>& height) {// 左指針,初始指向數組最左端int left = 0;// 右指針,初始指向數組最右端int right = height.size() - 1;// 記錄左側已遍歷區域的最高柱子高度int leftMax = 0;// 記錄右側已遍歷區域的最高柱子高度int rightMax = 0;// 最終接雨水的總量int res = 0;// 當左指針在右指針左側時,繼續遍歷(兩指針相遇則遍歷結束)while (left < right) {// 比較左右指針當前指向柱子的高度,優先處理較矮的一側if (height[left] < height[right]) {// 左側當前柱子高度 >= 左側已記錄的最高高度if (height[left] >= leftMax) {// 更新左側最高高度為當前柱子高度leftMax = height[left];} else {// 當前柱子可接雨水 = 左側最高高度 - 當前柱子高度res += leftMax - height[left];}// 左指針右移,處理下一個位置left++;} else {// 右側當前柱子高度 >= 右側已記錄的最高高度if (height[right] >= rightMax) {// 更新右側最高高度為當前柱子高度rightMax = height[right];} else {// 當前柱子可接雨水 = 右側最高高度 - 當前柱子高度res += rightMax - height[right];}// 右指針左移,處理下一個位置right--;}}// 返回最終接雨水的總量return res;}
};