欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:c++ 算法魅力-雙指針的實戰(zhàn)

柚子快報激活碼778899分享:c++ 算法魅力-雙指針的實戰(zhàn)

http://yzkb.51969.com/

目錄

1.雙指針的介紹

?1. 左右指針(對撞指針)

?2. 快慢指針

2.題目練習(xí)講解

?2.1 移動零

?算法思路

代碼展示

畫圖效果效果

2.2 復(fù)寫零

算法思路

?代碼展示

2.3 快樂數(shù)

算法思路

代碼展示

2.4 盛最多水的容器

算法思路

代碼展示

結(jié)束語

1.雙指針的介紹

雙指針?biāo)惴ㄊ且环N常用的算法技巧,通常用于解決數(shù)組或鏈表相關(guān)的題目。雙指針?biāo)惴ǖ暮诵乃枷胧鞘褂脙蓚€指針在數(shù)組或鏈表上移動,這里的指針并不是只是指指針,我們可以用數(shù)組下標(biāo)來代替,以達到解決問題的目的。根據(jù)具體問題,雙指針可以分為以下幾種類型:

?1. 左右指針(對撞指針)

左右指針通常用于處理數(shù)組中的問題,其中一個指針從數(shù)組的開始位置向后移動,另一個指針從數(shù)組的結(jié)束位置向前移動。

指針從兩端向中間移動。一個指針從最左端開始,另一個從最右端開始,然后逐漸往中間逼

近。

對撞指針的

終止條件一般是兩個指針相遇或者錯開(也可能在循環(huán)內(nèi)部找到結(jié)果直接跳出循環(huán)),也就是:

left == right (兩個指針指向同一個位置)

left > right (兩個指針錯開)

典型問題: 二分查找:在有序數(shù)組中查找一個特定的元素。 兩數(shù)之和:在數(shù)組中找到兩個數(shù),使它們的和等于一個給定的數(shù)。

?2. 快慢指針

快慢指針主要用于處理鏈表中的問題,兩個指針從同一位置出發(fā),一個指針(快指針)每次移動兩個節(jié)點,另一個指針(慢指針)每次移動一個節(jié)點。 ?典型問題: 判斷鏈表中是否有環(huán):Floyd 判圈算法(龜兔賽跑算法)。 找到鏈表的中間節(jié)點:快指針到達終點時,慢指針正好在中間。 雙指針?biāo)惴ǖ年P(guān)鍵在于指針的移動策略和終點的判斷條件,根據(jù)具體問題,雙指針的移動策略和判斷條件可能會有所不同。

2.題目練習(xí)講解

?2.1 移動零

283. 移動零 - 力扣(LeetCode)

給定一個數(shù)組?nums,編寫一個函數(shù)將所有?0?移動到數(shù)組的末尾,同時保持非零元素的相對順序。

請注意?,必須在不復(fù)制數(shù)組的情況下原地對數(shù)組進行操作。

示例 1:

輸入: nums = [0,1,0,3,12]

輸出: [1,3,12,0,0]

示例 2:

輸入: nums = [0]

輸出: [0]

?算法思路

在本題中,我們可以用一個 cur 指針來掃描整個數(shù)組,另一個 dest 指針用來記錄非零數(shù)序列

的最后一個位置。根據(jù) cur 在掃描的過程中,遇到的不同情況,分類處理,實現(xiàn)數(shù)組的劃分。

在 cur 遍歷期間,使 [0, dest] 的元素全部都是非零元素, [dest + 1, cur - 1] 的元素全是零。

[cur,n-1]是待處理的元素。

首先,我們,我們讓dest指向-1的位置,cur指向數(shù)組的首元素,通過循環(huán)控制cur的移動,無論cur指向誰,一次循環(huán)過后都要++,而當(dāng)cur指向的數(shù)據(jù)是非0元素時,我們就讓dest++,讓加之后的dest與cur進行元素交換。

詳細就是:

?cur 依次往后遍歷每個元素,遍歷到的元素會有下面兩種情況:

i. 遇到的元素是 0 , cur 直接 ++ 。因為我們的目標(biāo)是讓 [dest + 1, cur - 1] 內(nèi)

的元素全都是零,因此當(dāng) cur 遇到 0 的時候,直接 ++ ,就可以讓 0 在 cur - 1

的位置上,從而在 [dest + 1, cur - 1] 內(nèi);

ii. 遇到的元素不是 0 , dest++ ,并且交換 cur 位置和 dest 位置的元素,之后讓

cur++ ,掃描下?個元素。

? 因為 dest 指向的位置是非零元素區(qū)間的最后一個位置,如果掃描到一個新的非零元

素,那么它的位置應(yīng)該在 dest + 1 的位置上,因此 dest 先自增 1 ;

? dest++ 之后,指向的元素就是 0 元素(因為非零元素區(qū)間末尾的后一個元素就是

0 ),因此可以交換到 cur 所處的位置上,實現(xiàn) [0, dest] 的元素全部都是非零

元素, [dest + 1, cur - 1] 的元素全是零。

代碼展示

class Solution

{

public:

void moveZeroes(vector& nums)

{

for(int cur = 0, dest = -1; cur < nums.size(); cur++)

if(nums[cur]) // 處理?零元素

swap(nums[++dest], nums[cur]);

}

};

?當(dāng)然,我們也可以讓dest指向首元素,后續(xù)算法邏輯類似,只是變成了先交換在++。

class Solution

{

public:

void moveZeroes(vector& nums)

{

for(int cur = 0, dest = 0; cur < nums.size(); cur++)

if(nums[cur]) // 處理?零元素

swap(nums[dest++], nums[cur]);

}

};

畫圖效果效果

2.2 復(fù)寫零

1089. 復(fù)寫零 - 力扣(LeetCode)

算法思路

同樣這道題我們用雙指針的算法,我們首先普遍會想到定義兩個指針,從前向后開始復(fù)寫,從首元素開始移動,在移動過程中由于0會寫兩次,我們會發(fā)現(xiàn)后一個數(shù)據(jù)會被覆蓋就會達不到效果。

故當(dāng)我們換成從后向前復(fù)寫時,可以避免這種情況,但是我們需要找到復(fù)寫的最后一個元素。

我們還是定義兩個指針:

初始化兩個指針 cur = 0 , dest = -1?;

b. 找到最后一個復(fù)寫的數(shù):

i. 當(dāng) cur < n 的時候,一直執(zhí)行下面循環(huán):

? 判斷 cur 位置的元素:

? 如果是 0 的話, dest 往后移動兩位;

? 否則, dest 往后移動一位。

? 判斷 dest 時候已經(jīng)到結(jié)束位置,如果結(jié)束就終止循環(huán);

? 如果沒有結(jié)束, cur++ ,繼續(xù)判斷。

從 cur 位置開始往前遍歷原數(shù)組,依次還原出復(fù)寫后的結(jié)果數(shù)組:

i. 判斷 cur 位置的值:

1. 如果是 0 : dest 以及 dest - 1 位置修改成 0 , dest -= 2 ;

2. 如果?零: dest 位置修改成 0 , dest -= 1 ;

ii. cur-- ,復(fù)寫下一個位置。

while(cur>=0){

if(arr[cur])

arr[dest--]=arr[cur--];

else{

arr[dest--]=0;

arr[dest--]=0;

cur--;

}

}

我們發(fā)現(xiàn)有些情況會數(shù)組越界,超出一位,當(dāng)我們往前遍歷復(fù)寫的時候就會出現(xiàn)問題,因為數(shù)組外賦值了。

所以我們要處理數(shù)組越界的情況

?如果越界,n - 1 位置的值修改成 0 ; ?cur 向移動一步; dest 向前移動兩步。

?代碼展示

class Solution {

public:

void duplicateZeros(vector& arr) {

int cur=0,dest=-1;

int n=arr.size();

while(cur

if(arr[cur])

dest++;

else

dest+=2;

if(dest>=n-1)

break;

cur++;

}

if(dest==n){

arr[n-1]=0;

dest-=2;

cur--;

}

while(cur>=0){

if(arr[cur])

arr[dest--]=arr[cur--];

else{

arr[dest--]=0;

arr[dest--]=0;

cur--;

}

}

}

};

圖片效果展示

2.3 快樂數(shù)

202. 快樂數(shù) - 力扣(LeetCode)

算法思路

首先可以將題目解答猜成兩部分,第一部分是求取每個位數(shù)上的平方和,第二步就是與1進行比較。

通過快樂數(shù)的定義我們發(fā)現(xiàn)其實當(dāng)它結(jié)果為1時,也會陷入一個1的循環(huán)。所以不管那種過程,累加次都會陷入循環(huán),最終都會走到一個環(huán)中進行循環(huán)。

情況一:一直在 1 中死循環(huán),即 1 -> 1 -> 1 -> 1......

情況二:在歷史的數(shù)據(jù)中死循環(huán),但始終變不到 1

簡單證明一下:

經(jīng)過一次變化之后的最大值 9^2 * 10 = 810 ( 2^31-1=2147483647 。選一個更大的最

大?9999999999 ),也就是變化的區(qū)間在 [1, 810] 之間; ?根據(jù)「鴿巢原理」,一個數(shù)變化 811 次之后,必然會形成一個循環(huán); ?因此,變化的過程最終會走到一個圈里面,因此可以用「快慢指針」來解決

將「對于一個正整數(shù),每一次將該數(shù)替換為它每個位置上的數(shù)字的平方和」這一個

操作記為 x 操作

根據(jù)上述分析,我們可以知道,當(dāng)重復(fù)執(zhí)行?x 的時候,數(shù)據(jù)會陷入到一個「循環(huán)」之中。

而「快慢指針」有一個特性,就是在一個圓圈中,快指針總是會追上慢指針的,也就是說他們總會

相遇在一個位置上。如果相遇位置的值是 1 ,那么這個數(shù)一定是快樂數(shù);如果相遇位置不是 1的話,那么就不是快樂數(shù)。

代碼展示

class Solution {

public:

int ret(int n){

int sum=0;

while(n){

int a=n%10;

sum+=a*a;

n=n/10;

}

return sum;

}

bool isHappy(int n) {

int slow=n;

int fast=ret(n);

while(slow!=fast){

slow=ret(slow);

fast=ret(ret(fast));

}

return slow==1;

}

};

2.4 盛最多水的容器

11. 盛最多水的容器 - 力扣(LeetCode)

這道題我們首先會想到枚舉,通過暴力的解法將每一種的體積算出來,選出最大的。

lass Solution {

public:

int maxArea(vector& height) {

int n=height.size();

int ret=0;

for(int i=0;i

for(int j=i+1;j

ret = max(ret, min(height[i], height[j]) * (j - i));

}

}

return ret;

}

};

?但是這種解法會超時。所以需要換一種思路。我們可以采用對撞指針的思路。

算法思路

設(shè)兩個指針 left , right 分別指向容器的左右兩個端點,此時容器的容積 :

v = (right - left) * min( height[right], height[left])

容器的左邊界為 height[left] ,右邊界為 height[right] 。

我們假設(shè)「左邊邊界」小于「右邊邊界」。

如果此時我們固定一個邊界,改變另一個邊界,水的容積會有如下變化形式:

容器的寬度一定變小。

由于左邊界較小,決定了水的高度。

如果改變左邊界,新的水面高度度不確定,但是一定不會超過右邊的柱子高度,因此容器的容積可能會增大。

?

如果改變右邊界,無論右邊界移動到哪里,

新的水面的高度一定不會超過左邊界,也就是不會超過現(xiàn)在的水面高度,但是由于容器的寬度減小,因此容器的容器一定會變小的。

由此可見,左邊界和其余邊界的組合情況都可以舍去。所以我們可以 left++ 跳過這個邊界,繼續(xù)去判斷下一個左右邊界。

代碼展示

class Solution {

public:

int maxArea(vector& height) {

int left=0,right=height.size()-1;

int max=0;

for(int i=0;i

if(max<((right-left)*min(height[left],height[right])))

max=(right-left)*min(height[left],height[right]);

if(height[left]<=height[right])

left++;

else

right--;

}

return max;

}

};

結(jié)束語

相信通過本篇博客大家對雙指針?biāo)惴ㄓ辛艘欢ǖ牧私?,下篇博客我們將繼續(xù)講解三道例題加深對雙指針的印象。

最后感謝各位友友的支持,有不同的解法思路歡迎大家在評論區(qū)討論?。?!

柚子快報激活碼778899分享:c++ 算法魅力-雙指針的實戰(zhàn)

http://yzkb.51969.com/

推薦閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://m.gantiao.com.cn/post/19590705.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄