左神高階課例題

2021-10-05 13:30:45 字數 4429 閱讀 8366

給定乙個陣列arr,全是正數;乙個整數aim,求累加和等 於aim的,最長子陣列,要求額外空間複雜度o(1),時間 複雜度o(n)

思路就是利用兩個指標,來進行滑動視窗的計算。

#include

#include

#include

using

namespace std;

class

solution

int l =0;

int r =0;

int sum = nums[0]

;int len =0;

while

(r < nums.

size()

)else

if(sum < aim)

else

}return len;}}

;int

main()

; solution s;

cout<

getmaxlength

(nums,6)

<

return0;

}

ps:r和l均指向陣列中的第乙個元素,此時sum=nums[0],並且len=0,作為乙個開始的值。用int_min也可以,但是題目要求找不到返回0,就只能這樣定義了。

給定乙個陣列arr,值可正,可負,可0;乙個整數aim,求累加和小於等於aim的,最長子陣列,要求時間複雜度o(n)

#include

#include

#include

using

namespace std;

class

solution

//sums[i]:i開頭的所有子陣列的最小累加和

//ends[i]:取得最小累加和對應的右邊界

vector<

int> sums,ends;

sums.

resize

(nums.

size()

);ends.

resize

(nums.

size()

);//兩個陣列的最後乙個元素可直接寫出

sums[nums.

size()

-1]= nums[nums.

size()

-1];

ends[nums.

size()

-1]= nums.

size()

-1;//從後往前生成陣列

for(

int i = nums.

size()

-2; i >=

0; i--

)else

}//具體的處理邏輯

int r =0;

int sum =0;

int len =0;

for(

int start =

0; start < nums.

size()

; start++

) sum -

= r > start ? nums[start]:0

;//擴不動的話,減nums[i],判斷從nums[i+1]開始能不能繼續擴(這裡是加速的關鍵)

len =

max(len, r - start)

;//儲存len的最大值

r =max(r, start +1)

;//處理一開始就擴不動的情況

}return len;}}

;int

main()

; solution s;

cout<

maxlengthawesome

(nums,6)

;}

ps:臥槽這玩意真難理解!!!下面是所測例子的**模擬過程:

換錢的方法數

【題目】 給定陣列arr,arr中所有的值都為正數且不重複。每個值代表 一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一 個整數aim代表要找的錢數,求換錢有多少種方法。

【舉例】 arr=[5,10,25,1],aim=0。 組成0元的方法有1種,就是所有面值的貨幣都不用。所以返回1。 arr=[5,10,25,1],aim=15。 組成15元的方法有6種,分別為3張5元、1張10元+1張5元、1張 10元+5張1元、10張1元+1張5元、2張5元+5張1元和15張1元。所 以返回6。 arr=[3,5],aim=2。 任何方法都無法組成2元。所以返回0

ps:這個題是典型的動態規劃問題,也就是常說的找零問題。

#include

#include

//#include

using

namespace std;

class

solution

return dp[n]

[amount];}

};intmain()

; solution s;

cout<

change(10

,nums)

;}

其中的dp[i][j]表示:使用cions中前i個硬幣,湊出金額j,有dp[i][j]種湊法。

base case,dp[…][0] = 1表示:不用硬幣和用前i個硬幣,無論如何湊出0的方法都只有1種。dp[0][…] = 0表示:不使用任何硬幣,就無法湊出任何金額。如何轉移**中有注釋。下圖展示的是例子中的dp生成過程:

;}排成一條線的紙牌博弈問題

【題目】 給定乙個整型陣列arr,代表數值不同的紙牌排成一條線。玩家a和玩家b依次拿走 每張紙牌,規定玩家a先拿,玩家b後拿,但是每個玩家每次只能拿走最左或最右 的紙牌,玩家a和玩家b都絕頂聰明。請返回最後獲勝者的分數。

【舉例】 arr=[1,2,100,4]。 開始時玩家a只能拿走1或4。如果玩家a拿走1,則排列變為[2,100,4],接下來玩 家b可以拿走2或4,然後繼續輪到玩家a。如果開始時玩家a拿走4,則排列變為 [1,2,100],接下來玩家b可以拿走1或100,然後繼續輪到玩家a。玩家a作為絕頂 聰明的人不會先拿4,因為拿4之後,玩家b將拿走100。所以玩家a會先拿1,讓排 列變為[2,100,4],接下來玩家b不管怎麼選,100都會被玩家a拿走。玩家a會獲勝, 分數為101。所以返回101。 arr=[1,100,2]。 開始時玩家a不管拿1還是2,玩家b作為絕頂聰明的人,都會把100拿走。玩家b會 獲勝,分數為100。所以返回

#include

#include

using namespace std;

class solution

// 斜著遍歷陣列

for(

int l =

2; l <= n; l++

)else}}

pair<

int,

int> res = dp[0]

[n-1];

return res.first;}}

;int

main()

; solution s;

cout<

stonegame

(nums)

;}

下面的這個版本,其實就是用兩個表,這樣表中的元素就可以分別表示,而不是用pair來表示,兩種方法本質上沒有區別的。

#include

#include

#define max(a,b) (((a)>(b))?(a):(b))

#define min(a,b) (((a)

using namespace std;

intgetresult

(vector<

int>

,int);

intmain()

cout <<

getresult

(arr,n)

<< endl;

}int

getresult

(vector<

int>arr,

int n)

}//返回f和s中較大的乙個

return

max(f[0]

[n -1]

, s[0]

[n -1]);}

ps:好難~

左神牛課網講座第二發 演算法講解

從5隨機到7隨機及其擴充套件 題目 給定乙個等概率隨機產生1 5的隨機函式rand1to5如下 public intrand1to5 除此之外不能使用任何額外的隨機機制,請用rand1to5實現等概率隨機產生1 7的隨機函式rand1to7。補充題目 給定乙個以p概率產生0,以1 p概率產生1的隨機...

左神牛課網講座第一發 演算法講解

給定 乙個字串str和它的 乙個最長回 文 子串行strlps,返回字串str在任意 位置新增最少字元後,整體都是回 文串的其中 一種結果。例如 str ab1c2de34f3ghj21kl strlps 1234321 返回 ablk1c2dejhg3f4f3ghjed2c1klba 解答 1,依...

左神初級班 (二)

實現一種狗貓佇列的結構,要求如下 使用者可以呼叫add方法將cat類或dog類的例項放入佇列中 使用者可以呼叫pollall方法,將佇列中所有的例項按照進佇列的先後順序依次彈出 使用者可以呼叫polldog方法,將佇列中dog類的例項按照進佇列的先後順序依次彈出 使用者可以呼叫pollcat方法,將...