題目:
給定乙個非負整數陣列,你最初位於陣列的第乙個位置。
陣列中的每個元素代表你在該位置可以跳躍的最大長度。
判斷你是否能夠到達最後乙個位置。
方法一: 回溯法
有一組資料超時。
遍歷每個元素,對於每個元素i,先跳最大的步數nums[i],到達下乙個元素next。
如果能夠跳出這個陣列(nums[i]+i>=nums.length-1),那麼它一定可以跳到這個陣列的最後乙個元素。如果不能夠跳出這個陣列:
(1)next的值如果為0,則這條路是不可行的,則進行回溯,注意:是進行回溯,不能直接返回false。
(2)next的值如果不為0,則從該結點開始進行遞迴
**實現如下:
public
boolean
canjump
(int
nums,
int start)
}return
false
;}
當我們對方法一進行遞迴樹的分析,
輸入: [3,2,1,0,4]元素3
2104
角標012
34注c(i)==canjump(nums,i)
我們可以看出遞迴樹有很多重複的子問題,因此我們對它進行剪枝,因為 c(3)已經被計算過不能走了,因此我們將c(2)中的c(3)剪去,而c(2)不能到達c(0),因此c(2)也不能走到。c(1)中的c(2)和c(3)之前都已經證明不能走,因此沒有必要再進行計算。
根據上述優化,我們引入第二種方法。
方法二:動態規劃記憶法(自上而下)
利用乙個demo陣列,陣列元素初始化為0,對所有情況進行標記,如果能夠到達最後乙個元素,則標記為1,不能到達標記為-1。
**修改:在return前要先賦值,在遍歷前要先看在記憶裡有沒有訪問過
public
boolean
canjump
(int
nums)
public
boolean
helper
(int
nums,
int start,
int[
] demo)
//在遍歷前要先看在記憶裡有沒有訪問過
if(demo[start]==0
)if(nums[start + i]!=0
)}} demo[start]=-
1;//在return前要先賦值,
return
false;}
return demo[start]==1
;}
方法三:動態規劃製表法(自下而上)
記憶法(自上而下)是從左往右遍歷元素看是否是能夠到達最後乙個元素。那麼**法(自下而上)就是從右邊到左邊去遍歷。
最右邊乙個肯定是,自身能夠到達自身(can)
左邊的是不是,取決於它能不能跳到它右邊的can,也就是說在它能跳的範圍之內是不是有can
如果它能夠跳到can,則說明它也是can,否則,它是can』t
依次往左,看最左邊乙個是不是can
public
boolean
canjump
(int
nums)
}return table[0]
==1;}
我們可以將上述問題再進行優化,本來看乙個元素是不是can,是遍歷它右邊的每個元素看有沒有can,現在我們不用去遍歷它右邊的每個元素,而是利用乙個變數closed
跟蹤它右邊離它最近的can。於是我們引入貪心演算法。
方法四:貪心演算法
這個解法是貪心演算法的原因是它右邊的元素已經處理完,離它最近的can也已經被我們用closed
跟蹤了,因此,我們不用再去考慮我們已經解決的右邊元素。而動態規劃還要繼續遍歷右邊的元素以尋找can。這就是貪心演算法和動態規劃最主要的區別。貪心演算法不用再去考慮已經解決的子問題。關於貪心演算法可以參考這篇文章
我們可以將演算法再進行優化,因為closed
是用來標記最左邊的can,因此,只要closed
是0,則第0個元素是最左邊的can。因此,我們有方法五。
方法五:貪心演算法優化
LeetCode 刻意練習03 移除元素
題目 引數列表給定乙個陣列 nums 和乙個值 val,你需要原地移除所有數值等於 val 的元素,返回值 移除後陣列的新長度。不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 o 1 額外空間的條件下完成。思路 遍歷陣列,如果遇到不為val的值則將其賦值給陣列第i元素,並且i 否則繼續遍歷...
《刻意練習》5
不管是 還是體育等等領域,該領域中最傑出的人在青少年時期總是經過了漫長的練習才取得了如今的成績。並且投入的時間與取得的成績成正比。1 首先,它需要乙個已經得到合理發展的行業或領域,也就是說,在那一行業或領域之中,最傑出的從業者已達到一定程度的表現水平,使他們與其他剛剛進入該行業或領域的人們明顯地區分...
LeetCode刻意練習13 羅馬數字轉化為整數
題目 給定乙個羅馬數字,將其轉換成整數。輸入確保在 1 到 3999 的範圍內。思路 羅馬數字的特點是將上面的符號按降序排序。e.g.m s first,followed by d s,etc.然而,在一些特殊的例子裡,為了防止出現4個符號重複 such as iiii or x 會用以下公升序來表...