leetcode 55. Jump Game

這裏寫圖片描述

 題目的要求是給出一個數組,數組中每個元素的數值代表可以從這個下標“跳躍”到的最大距離(注意是最大,也就是說可以跳小於這個距離)。初始下標是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;
            //  由於set內部的值從小到大,所以不用擔心越界問題,因爲越界之前已經返回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;
        //  從0開始遍歷,直到數組的最後,或者是
        //  達到了能到達的最大下標(此時必定沒有超過數組的最大下標)
        for (i = 0; i < asize&&i <= reach; i++) {
            //  從下標i能跳到的最遠下標是i + nums[i]
            //  如果這個下標大於reach,那麼更新reach
            if (i + nums[i] > reach) {
                reach = i + nums[i];
            }
        }
        //  如果i是到達最大下標才退出的循環,那麼返回true,否則false
        return i == asize;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章