[寶寶也能看懂的活動篇][30-Day LeetCoding Challenge] 第七天

Hi 你們好,我是張小豬。歡迎來到『寶寶也能看懂』系列特別篇 - 30-Day LeetCoding Challenge。這是一個 leetcode 官方的小活動。能夠在官網看到,從 4 月 1 號開始,天天官方會選出一道題,在 24 小時內完成便可得到一點小獎勵。git

這裏是 4 月 7 號的題,是一道新題,不在以前的題目列表中 -- 『Counting Elements』github

題目描述

Given an integer array arr, count element x such that x + 1 is also in arr.
給定一個整數數組 arr,對於其中的任何一個 x,若是 x + 1 也在數組中,則計數結果加一。shell

If there're duplicates in arr, count them seperately.
若是存在多個相同的 x,咱們須要分別進行計數。segmentfault

示例 1:數組

輸入: arr = [1,2,3]
輸出: 2
解釋: 1 and 2 are counted cause 2 and 3 are in arr.

示例 2:優化

輸入: arr = [1,1,3,3,5,5,7,7]
輸出: 0
解釋: No numbers are counted, cause there's no 2, 4, 6, or 8 in arr.

示例 3:spa

輸入: arr = [1,3,2,3,5,0]
輸出: 3
解釋: 0, 1 and 2 are counted cause 1, 2 and 3 are in arr.

示例 4:code

輸入: arr = [1,1,2,2]
輸出: 2
解釋: Two 1s are counted cause 2 is in arr.

數據範圍:blog

  • 1 <= arr.length <= 1000
  • 0 <= arr[i] <= 1000

官方難度

UNKNOWN(我猜 EASY)element

解決思路

雖然是一道新題,不過看起來也很直白。咱們能夠經過記錄出現過的數字,而後再判斷是否存在 +1 的數字,來輕鬆 AC。

直接方案

思路如上,代碼以下:

const countElements = (arr) => {
  const counts = new Uint8Array(1001);
  let ret = 0;
  for (const val of arr) counts[val] = 1;
  for (const val of arr) counts[val + 1] && ++ret;
  return ret;
};

換個思路

上面的代碼裏,咱們是經過兩輪遍從來完成計算。那是否能夠只用一輪遍從來實現呢?

若是隻用一輪遍歷,就意味着在遍歷過程當中咱們不會有完整的數字存在與否的信息,也就意味着咱們須要結合當前的數據來逐漸推出結果。不過咱們很容易發現,在遍歷的過程當中其實只有兩種狀況:

  • 若是存在 +1 的數字,則咱們須要對當前數字進行計數,而且當前數字將被消耗掉,不能在之後繼續用做累計。
  • 若是存在 -1 的數字,則咱們須要對以前全部的 -1 數字進行計數,而且把它們消耗掉。

因此咱們能夠添加一種特殊的標識,用以指示當前數字是存在的,可是已經被徹底消耗掉了。從而完成整個計數過程。具體代碼以下:

const countElements = (arr) => {
  const counts = new Uint16Array(1001);
  const MAGIC = 2000;
  let ret = 0;
  for (const val of arr) {
    if (counts[val - 1] && counts[val - 1] !== MAGIC) {
      ret += counts[val - 1];
      counts[val - 1] = MAGIC;
    }
    counts[val + 1] ? (++ret, (counts[val] = MAGIC)) : ++counts[val];
  }
  return ret;
};

優化

其實這裏可能有的小夥伴已經發現了,在上面的思路中,若是一個數字第一次完成了在狀況 2 中的處理,那麼它將不會再遇到狀況 2。因此咱們能夠省去相關的判斷,其實也就是省去這個特殊的標識,直接就能完成計數的過程。具體代碼以下:

const countElements = (arr) => {
  const counts = new Uint16Array(1001);
  let ret = 0;
  for (const val of arr) {
    counts[val - 1] && !counts[val] && (ret += counts[val - 1]);
    counts[val + 1] && ++ret;
    ++counts[val];
  }
  return ret;
};

總結

雖然是一道新題目,不過想 AC 仍是很是容易的,由於思路是很是明顯的。只不過從兩輪遍歷到一輪遍歷,可能稍微須要思考一下。

這裏其實頗有可能小夥伴們會直接跳過第二種方案,想到第三種方案。不太小豬仍是把它寫了出來,當作中間思路的過渡。但願能幫到有須要的小夥伴。

若是以爲不錯的話,記得『三連』哦。小豬愛大家喲~

相關連接

qrcode_green.jpeg

相關文章
相關標籤/搜索