題目的要求是給出一個數組,數組中每個元素的數值代表可以從這個下標“跳躍”到的最大距離(注意是最大,也就是說可以跳小於這個距離)。初始下標是0,問能否跳到數組最大的下標。
其實第一眼看到這道題,我以爲是要用分治算法或者構建一棵樹之類的,講真,用樹真的可以做的好嗎……後來我的想法是,從下標0開始,記錄它能到達的所有下標,然後再按順序訪問這些下標,看它們能跳轉到哪裏,能否跳轉到最大的下標。所以我一開始採用了set來存儲,利用set元素的唯一性,把能到的下標都插進去,直到能夠跳到最後或者set遍歷完還沒到最後,結果75個測試中恰恰有個巨長的測試會超時,其他都通過。明顯我的想法雖然離目標不遠,但還是太複雜了。於是我決定每次插入前先判斷能否使得set中元素增加(能到達的最大下標增大),不能就不處理了。於是我第一次pass了這道題,但只超過了9%的提交,明顯有待改進。
以下是第一次成功的代碼,僅僅是留個紀念,因爲後面的方法更簡潔
class Solution {
public:
bool canJump(vector<int>& nums) {
int asize = nums.size();
if (asize == 0) return false;
if (asize == 1) return true;
set<int> myset;
myset.insert(0);
set<int>::iterator it = myset.begin();
int max = 0;
while(it != myset.end()) {
if (max >= asize - 1) return true;
int diff = *it + nums[*it] - max;
if (diff > 0) {
for (int i = 1; i <= diff; i++) {
myset.insert(max + i);
}
max = *it + nums[*it];
}
it++;
}
return false;
}
};
爲了尋求更快速的方法,我查看了討論區,並且發現我把能到達的元素全部記錄起來完全是多餘的,因爲能跳到的最大下標之前的所有下標都是可達的,所以只記錄當前最大下標就行了。於是簡化之後,超過了82.74%的提交。
改進後的代碼如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
int asize = nums.size();
int reach = 0;
int i = 0;
for (i = 0; i < asize&&i <= reach; i++) {
if (i + nums[i] > reach) {
reach = i + nums[i];
}
}
return i == asize;
}
};