日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

Leetcode1712. 将数组分成三个子数组的方案数[C++题解]:双指针和前缀和

發(fā)布時(shí)間:2025/4/5 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Leetcode1712. 将数组分成三个子数组的方案数[C++题解]:双指针和前缀和 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

      • 本題分析
      • 題目鏈接

本題分析

題目重述: 給定一個(gè)非負(fù)的數(shù)組,要求將其分成3個(gè)非空的三段,要求每一段的數(shù)字之和依次遞增(可以相等),求總共有幾種分法。

題目解答:

雙指針?biāo)惴?/p>

思路:枚舉第二個(gè)分界點(diǎn),看第一個(gè)分界點(diǎn)有多少種選擇 。

數(shù)組下標(biāo)從1開始,即從1到n: a[1] ,a[2],…a[n], 第二個(gè)分界點(diǎn)下標(biāo)是i,第一個(gè)分界點(diǎn)下標(biāo)是x,這里下標(biāo)屬于后一段。這樣把數(shù)組分成三段(用下標(biāo)來表示):[1~x-1], [x ~i-1],[ i ~ n]. 三段之和分別記為A,B,C

對(duì)于分界點(diǎn)i,我們看第一個(gè)分界點(diǎn)x的取值范圍,假設(shè)其可取的最小下標(biāo)為j,可取的最大下標(biāo)為k,那么對(duì)于第二個(gè)分界點(diǎn)i,滿足題意的方案數(shù)就有:k-j+1 種。

比如樣例,

輸入:nums = [1,2,2,2,5,0] 輸出:3 解釋:nums 總共有 3 種好的分割方案: [1] [2] [2,2,5,0] [1] [2,2] [2,5,0] [1,2] [2,2] [5,0] 下標(biāo)從1開始123456
數(shù)組內(nèi)容122250

假設(shè)第二個(gè)分界點(diǎn)下標(biāo)i=4,則C=7,第一個(gè)分界點(diǎn)x可取多少呢? (j,k)=(3,3),故此時(shí)的方案數(shù): 3-3+1=1種。

假設(shè)第二個(gè)分界點(diǎn) i=5,則C=5,那么第一個(gè)分界點(diǎn)x可取多少呢? (j,k)=(3,4),故此時(shí)的方案數(shù): 4-3+1=2種。

總的方案數(shù)就是1+2=3種。

下面的問題就是這個(gè) j和k 怎么求?

j的含義是:i給定之后, 第一個(gè)分界點(diǎn)最靠前可以取到什么位置。

i需要滿足什么呢?

j越往左走,那么中間B就會(huì)越大,為了滿足B≤C,那么必然j有下界。

在第二個(gè)分界點(diǎn)往后走的時(shí)候,C在變小,為了滿足B≤C,j也應(yīng)該往后走。也就是說,j會(huì)隨著i向右移而單調(diào)向右移

k的含義是:i給定之后,第二個(gè)分界點(diǎn)最靠后可以取到什么位置。

k需要滿足什么呢?

k需要滿足a[k]~a[i-1]的和≥ a[1] ~a[k-1]的和,即B≥A。

k往右走,在i固定時(shí),B會(huì)變小,A會(huì)變大,為了滿足B≥A,必然存在一個(gè)最大的k,越過了這個(gè)邊界,就不再滿足B≥A。

根據(jù)上面 j的推理,可以利用反證法證明, k會(huì)隨著i向右移而單調(diào)向右移

總之:最小取值j由右邊(C≥B)限制, 最大取值 k由左邊(A≤B)限制。

當(dāng)然還有小技巧:可以使用前綴和來求出一段的和:通過O(1)的時(shí)間求出一段的和。

注意:下面對(duì)代碼進(jìn)行解釋

對(duì)于邊界(j,k)的判斷思路不太一樣

while(s[n]-s[i-1] < s[i-1]-s[j-1]) j++; while( k+1<i && s[k] <= s[i-1]-s[k]) k++;

下面進(jìn)行解釋:

對(duì)于 左邊界j:左邊界被右邊限制,只要B大于C,j就一直j++,直到第一個(gè)滿足B小于等于C。這就是滿足題意的第一個(gè)分界點(diǎn)的最小取值,即左邊界。

對(duì)于右邊界k:右邊界k被左邊限制,我們要試探性地往右走:對(duì)于下標(biāo)是k+1的第一個(gè)分界點(diǎn),是否滿足 A小于等于B,如果滿足,就繼續(xù)k++。當(dāng)然,第一個(gè)下標(biāo)永遠(yuǎn)小于第二個(gè)下標(biāo)i,嘗試k+1時(shí)也要滿足k+1<i.

ac代碼

class Solution { public:int waysToSplit(vector<int>& nums) {int n = nums.size(),mod = 1e9 +7;vector<int> s(n+1); //前綴和數(shù)組for(int i=1;i<=n;i++) s[i] =s[i-1]+nums[i-1]; //下標(biāo)往后移動(dòng)了一個(gè),從1開始int res=0;//枚舉第二個(gè)分界點(diǎn)i,記住下標(biāo)從1開始for( int i=3, j=2, k=2; i<= n; i++){//判斷(j,k)的位置//對(duì)于左邊界j:如果B>C,j一直往右移動(dòng),直到B≤Cwhile(s[n]-s[i-1] < s[i-1]-s[j-1]) j++;//對(duì)于右邊界k: 如果A一直小于等于B,k就一直往右移//本身是A小于等于B 即[1,k-1] ≤ [k,i-1]//試探一下,看k取k+1是否成立,如果成立就k++。//現(xiàn)在要試探k+1 即 [1,k] ≤ [k+1, i-1]while( k+1<i && s[k] <= s[i-1]-s[k]) k++;if(j<=k && s[k-1] <= s[i-1]-s[k-1] && s[n]-s[i-1] >= s[i-1]-s[j-1] )res=( res+ k-j+1) %mod;}return res;} };

題目鏈接

Leetcode1712. 將數(shù)組分成三個(gè)子數(shù)組的方案數(shù)

總結(jié)

以上是生活随笔為你收集整理的Leetcode1712. 将数组分成三个子数组的方案数[C++题解]:双指针和前缀和的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。