【每日一題】(27題)算法題:如何使用多種解決方案來實現跳一跳游戲?

關注「松寶寫代碼」,精選好文,每日一題

作者:saucxs | songEagle

2020,實「鼠」不易

2021,「牛」轉乾坤

風勁潮涌當揚帆,任重道遠須奮蹄!

一、前言

2020.12.23 立的 flag,每日一題,題目類型不限制,涉及到JavaScript,Node,Vue,React,瀏覽器,http,算法等領域。

本文是:【每日一題】(27題)算法題:如何使用多種解決方案來實現跳一跳游戲?

昨天發了文章【每日一題】(26題)算法題:最長公共前綴?被人一頓吐槽,槽點太多了,比如:

  • 能不能給出最優解?
  • 不講基礎題目,能不能講一下稍微難點的算法題?

哈哈,我以為沒有人看呢?原來還是有人在看哈,簡單說明一下:

  • 每一個問題背后有多種解決方案,我們可以從最初的解決方案出發,逐步優化,找出問題所在。
  • 基礎題目有一定的道理,每一個算法可以融入到千變萬化的場景中,從而就有了成千上萬的題目,你需要從場景中抓住重點,提取信息,匹配到合適的算法,最終解決。

[圖片上傳失敗...(image-cb8894-1611071808563)]

二、題目

昨天我們還談了很多基礎問題,我們先來看一下我們說的基礎題目,也就是常說的「爬樓梯問題」或者「跳一跳游戲」。

問題描述:

給定一個非負整數數組,你最初位于數組的第一個位置。數組中的每個元素代表你在該位置可以跳躍的最大長度。判斷你是否能夠到達最后一個位置。

例子1:

輸入: [2,3,1,1,4]
輸出: true
解釋: 我們可以先跳 1 步,從位置 0 到達 位置 1, 然后再從位置 1 跳 3 步到達最后一個位置。

例子2:

輸入: [3,2,1,0,4]
輸出: false
解釋: 無論怎樣,你總會到達索引為 3 的位置。但該位置的最大跳躍長度是 0 , 所以你永遠不可能到達最后一個位置。

三、解決方案

1、回溯方法

這是一個效率低的方案,其中我們嘗試從第一個位置跳到最后一個位置上的跳躍方式。我們第一個位置開始,跳到所有可能達到的步數。我們重復這個過程,直到達到最后一個位置。當達不到的時候我們回溯。

var backtrackingJumpLittle = function (numbers, startIndex = 0, currentJumps = []) {
  if (startIndex === numbers.length - 1) {
    return true;
  }

  const maxJumpLength = Math.min(
    numbers[startIndex],
    numbers.length - 1 - startIndex,
  );

  for (let jumpLength = maxJumpLength; jumpLength > 0; jumpLength -= 1) {
    const nextIndex = startIndex + jumpLength;
    currentJumps.push(nextIndex);
    const isJumpSuccessful = backtrackingJumpLittle(numbers, nextIndex, currentJumps);
    if (isJumpSuccessful) {
      return true;
    }
    currentJumps.pop();
  }
  return false;
}

我們來分析一下時間復雜度和空間復雜度:

  • 時間復雜度:O(2^n)。從第一個位置到最后一個位置有2的n次方跳躍方式,其中narray的長度為nums。

  • 空間復雜度:O(n)。遞歸需要額外的內存用于堆棧。

2、自頂向下動規方法

自上而下的動態規劃可以被認為是優化的回溯。它依賴于這樣的觀察:一旦我們確定某個臺階是可以達到終點,還是不能達到終點,那么這個結果將永遠不會改變。這意味著我們可以存儲結果,而不必每次都重新計算。

因此,對于數組中的每個位置,我們都記住該位置是好是壞。我們將這個其值設為以下之一:good,bad,unknow。

var dpTopDownJumpLittle = function (
  numbers,
  startIndex = 0,
  currentJumps = [],
  cellsGoodness = [],  // 用來存當前臺階的狀態
) {
  if (startIndex === numbers.length - 1) {
    return true;
  }

  const currentCellsGoodness = [...cellsGoodness];
  if (!currentCellsGoodness.length) {
    numbers.forEach(() => currentCellsGoodness.push(undefined));
    currentCellsGoodness[cellsGoodness.length - 1] = true;
  }

  const maxJumpLength = Math.min(
    numbers[startIndex],
    numbers.length - 1 - startIndex,
  );

  for (let jumpLength = maxJumpLength; jumpLength > 0; jumpLength -= 1) {
    const nextIndex = startIndex + jumpLength;
    if (currentCellsGoodness[nextIndex] !== false) {
      currentJumps.push(nextIndex);
      const isJumpSuccessful = dpTopDownJumpLittle(
        numbers,
        nextIndex,
        currentJumps,
        currentCellsGoodness,
      );
      if (isJumpSuccessful) {
        return true;
      }
      currentJumps.pop();
      currentCellsGoodness[nextIndex] = false;
    }
  }
  return false;
}
  • 時間復雜度::O(n^2)。對于數組中的每個元素,例如i,我們正在尋找nums[i]其右邊的下一個元素,目的是尋找一個良好的索引。

  • 空間復雜度:O(2 * n) = O(n)。首先n起源于遞歸。其次n來自存儲當前步數狀態的用法。

3、自下向上動規方法

這一步驟為將來的優化打開了可能。通常通過嘗試從上至下的方法顛倒步驟的順序來消除遞歸。

var dpBottomUpJumpLittle = function(numbers) {
  const cellsGoodness = Array(numbers.length).fill(undefined);
  cellsGoodness[cellsGoodness.length - 1] = true;
  for (let cellIndex = numbers.length - 2; cellIndex >= 0; cellIndex -= 1) {
    const maxJumpLength = Math.min(
      numbers[cellIndex],
      numbers.length - 1 - cellIndex,
    );

    for (let jumpLength = maxJumpLength; jumpLength > 0; jumpLength -= 1) {
      const nextIndex = cellIndex + jumpLength;
      if (cellsGoodness[nextIndex] === true) {
        cellsGoodness[cellIndex] = true;
        break;
      }
    }
  }
  return cellsGoodness[0] === true;
}
  • 時間復雜度:: O(n^2)

  • 空間復雜度:O(n)

[圖片上傳失敗...(image-a3c869-1611071808563)]

4、貪心算法

一旦我們的代碼處于自下而上的狀態,我們就可以做最后一個重要的觀察。從一個給定的位置,當我們試圖看看是否能跳到一個好的位置時,我們只使用第一個。換句話說,最左邊的一個。如果我們把這個最左邊的好位置作為一個單獨的變量來跟蹤,我們可以避免在數組中搜索它。不僅如此,我們還可以完全停止使用數組。

var greedyJumpLittle = function(numbers) {
  let leftGoodPosition = numbers.length - 1;
  for (let numberIndex = numbers.length - 2; numberIndex >= 0; numberIndex -= 1) {
    const maxCurrentJumpLength = numberIndex + numbers[numberIndex];
    if (maxCurrentJumpLength >= leftGoodPosition) {
      leftGoodPosition = numberIndex;
    }
  }
  return leftGoodPosition === 0;
}
  • 時間復雜度::O(n)。我們正在遍歷nums數組,因此要遍歷n,其中n的長度是array的長度nums。

  • 空間復雜度:O(1)。我們沒有使用任何額外的內存。

我在leetcode上測試了一下,發現空間占用還是很大,運行時間76ms左右,內存消耗38MB左右。

[圖片上傳失敗...(image-c940fd-1611071808563)]

謝謝支持

1、文章喜歡的話可以「分享,點贊,在看」三連哦。

2、作者昵稱:saucxs,songEagle,松寶寫代碼。「松寶寫代碼」公眾號作者,每日一題,實驗室等。一個愛好折騰,致力于全棧,正在努力成長的字節跳動工程師,星辰大海,未來可期。內推字節跳動各個部門各個崗位。

3、長按下面圖片,關注「松寶寫代碼」,是獲取開發知識體系構建,精選文章,項目實戰,實驗室,每日一道面試題,進階學習,思考職業發展,涉及到JavaScript,Node,Vue,React,瀏覽器,http等領域,希望可以幫助到你,我們一起成長~

[圖片上傳失敗...(image-24253e-1611071808564)]

字節內推福利

  • 回復「校招」獲取內推碼
  • 回復「社招」獲取內推
  • 回復「實習生」獲取內推

后續會有更多福利

學習資料福利

回復「算法」獲取算法學習資料

往期「每日一題」

1、JavaScript && ES6

2、瀏覽器

3、Vue

4、算法

5、Http

6、Node

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容