Leetcode刷題 190713 動態規劃

2021-09-29 05:11:49 字數 3110 閱讀 6607

輸入乙個陣列,陣列中每個元素代表乙個房子,我們作為robber可以對每個房子進行rob。但是規定不能同時又兩個相鄰的房子被robbed。陣列中每個元素的值代表房子的價值,需要我們輸出經過rob後最大的收益是多少。

很明顯考察的是動態規劃,每檢查乙個房子都有兩種狀態即robno-rob。對應的價值方程為:

$result(i) = max(rob(i), norob(i))$

$rob(i) = nums[i] + result(i - 2)$

$norob(i) = result(i - 1)$

其中,$result(i)$ 表示檢查第i個房子最後的收益是多少,它應該為這個房子rob或no-rob這兩種情況中較大的那個。$nums$表示輸入全部房子資訊的陣列。可見,如果rob,根據規則我們不能rob兩個連續的房子,所以$rob(i)$式子中有$result(i - 2)$這一項,整個方程表示當前這個房子的價值加向前兩個房子計算後的價值。no-rob比較好理解,什麼都不做即為上乙個房子計算後的價值。

可能會有不清晰的地方:為什麼計算第$i$個房子的價值不需要考慮$i+1$的房子是不是被robbed?其實這裡體現動態的乙個效果,當檢查$i+1$時,過去的$i$即為那時的$i-1$,也就是不必為未來考慮,現在的情況便是未來的過去。只需要保證現在和現在的過去吻合題意即可,因此上面的方程可以解釋全部的情況。稍微有一點點繞,不過相信作為讀者的你一定能理解這個地方。我做題的時候思考過這個問題,個人感覺還是有點繞的……

根據總結的方程直觀模擬

123

4567

891011

1213

1415

1617

1819

2021

2223

2425

2627

2829

3031

private

static

inttle_process

(int nums, int i)

// i=0, 只有一種可能即rob

if (i == 0)

// i=1, nums陣列中只有兩個,選較大的那個

if (i == 1)

int max = nums[i];

for (int j = i; j >= 0; j--)

return max;

}// main

public

introb

(int nums)

很明顯這個實現必定tle的,當nums稍大一點較前面的只便會被重複計算很多遍。

123

4567

891011

1213

1415

1617

1819

2021

2223

2425

2627

2829

3031

3233

3435

3637

3839

4041

4243

4445

46

// use cache

private

static

intcacheprocess

(int nums, int i, int cache)

// 不在cache中,需要算

int max = nums[i];

for (int j = i; j >= 0; j--)

cache[i] = max;

return max;

}public

introb

(int nums)

if (nums.length == 1)

// cache中第i個記錄著方程中result(i)的值

int cache = new

int[nums.length];

cache[0] = nums[0];

cache[1] = nums[0] > nums[1] ? nums[0] : nums[1];

// 沒利用的初始化為-1

for (int i = 2; i < cache.length; i++)

return cacheprocess(nums, nums.length - 1, cache);

}

這種方式減少了很多的重複計算。

123

4567

891011

1213

1415

1617

1819

2021

2223

2425

2627

2829

3031

3233

3435

3637

// 取消遞迴 + cache空間優化

public

introbspaceoptimization

(int nums)

int lastsecond = nums[0];

// deal [1],處理特殊情況

if (nums.length == 1)

int lastfirst = nums[0] > nums[1] ? nums[0] : nums[1];

// deal [1, 2],處理特殊情況

if (nums.length == 2)

int max = 0;

// main process 自底向上,使用兩個變數代替cache陣列盡可能減少cache空間,同時取消遞迴

for (int i = 2; i < nums.length; i++)

return max;

}

通過觀察方程我們發現式子中只出現了$result(i-1)$和$result(i-2)$這兩個需要重複計算的變數。因此我們沒必要使用陣列儲存全部的過程而只是動態的記錄這兩個變數的值即可。

思路參考:csdn hankinghu 演算法-動態規劃 dynamic programming—從菜鳥到老鳥 19/07/13

開始刷題LeetCode

今天決定開始刷題,每天至少一題,如果題目確實沒有解決出來沒有關係,但是要保證每天至少接觸了一道新的題目!一定要堅持下去,現在是個菜鳥可能會感覺有點難度,堅持下去,總有一天會好的!今天是第一天,做的第乙個題目 reverse words in a string given an input strin...

leetcode刷題歷程

難度 簡單 題目 給定乙個整數陣列 nums 和乙個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。你可以假設每種輸入只會對應乙個答案。但是,你不能重複利用這個陣列中同樣的元素。示例 給定 nums 2,7,11,15 target 9 因為 nums 0 ...

LeetCode刷題總結

123 4567 891011 12 元素交換 swap a 1 a 3 sort排序 sort a.begin a.end 陣列顛倒 reverse a.begin a.end 陣列元素置為0 memset a,0,a.size 陣列取值 a.push back 定義二維陣列 vector vec...