Hi 你們好,我是張小豬。歡迎來到『寶寶也能看懂』系列之 leetcode 周賽題解。git
這裏是第 175 期的第 1 題,也是題目列表中的第 1346 題 -- 『檢查整數及其兩倍數是否存在』github
給你一個整數數組 arr
,請你檢查是否存在兩個整數 N
和 M
,知足 N
是 M
的兩倍(即,N = 2 * M
)。面試
更正式地,檢查是否存在兩個下標 i
和 j
知足:shell
i != j
0 <= i, j < arr.length
arr[i] == 2 * arr[j]
示例 1:segmentfault
輸入:arr = [10,2,5,3] 輸出:true 解釋:N = 10 是 M = 5 的兩倍,即 10 = 2 * 5 。
示例 2:數組
輸入:arr = [7,1,14,11] 輸出:true 解釋:N = 14 是 M = 7 的兩倍,即 14 = 2 * 7 。
示例 3:優化
輸入:arr = [3,1,7,11] 輸出:false 解釋:在該狀況下不存在 N 和 M 知足 N = 2 * M 。
提示:spa
2 <= arr.length <= 500
-10^3 <= arr[i] <= 10^3
EASYcode
題目的描述比較正式,若是簡單的說其實就是,給定了一個數組,須要確認其中是否有一個數是另外一個數的兩倍。blog
相信一直看小豬題解的小夥伴們讀完這道題就會有思路啦,畢竟也是 EASY 難度,小豬也就不作過多的分析啦。惟一須要提到的一點就是,咱們是須要尋找到另外一個數而不是當前數,即若是數組中只存在一個 0,那麼是不能返回 true
的。而且,若是 x
是 y
的兩倍,那麼 y
必然是 x
的一半。這句話看起來是廢話,不過它背後的意思是,咱們在遍歷的過程當中,只須要進行單方向的檢查便可,不用對左右兩個方向都檢查了。
下面給出兩種常見方案:
暴力搜索沒有過多能夠說的內容,只須要注意到上面分析中提到的兩個問題便可。具體流程以下:
基於這個流程,咱們能夠實現相似下面的代碼:
const checkIfExist = arr => { for (let i = 0; i < arr.length; ++i) { for (let j = i + 1; j < arr.length; ++j) { if (arr[j] === arr[i] << 1 || arr[j] === arr[i] / 2) return true; } } return false; };
對於存儲歷史值的方案,咱們須要用到額外的空間來記錄。這裏咱們能夠用定長數組,也能夠用集合。具體流程以下:
基於這個流程,小豬這裏把兩種儲存方式的代碼都寫了出來,供小夥伴們參考:
// 基於定長 Uint8Array 記錄 const checkIfExist = arr => { const neg = new Uint8Array(1000); const pos = new Uint8Array(1000); for (const val of arr) { const arr = val > 0 ? pos : neg; const v2 = Math.abs(val); if (arr[v2 << 1] === 1 || arr[v2 / 2]) return true; arr[v2] = 1; } return false; };
// 基於 Set 記錄 const checkIfExist = arr => { const set = new Set(); for (const val of arr) { if (set.has(val << 1) || set.has(val / 2)) return true; set.add(val); } return false; };
周賽第一題慣例送分。其實這個問題在比較初級的面試中小豬也用過,其中直接的暴力搜索方案是很容易被面試者提到,但是能提到 O(n) 的優化方案卻不到一半。
小豬也不清楚具體的緣由,因此這裏專門把兩種方案都寫了出來。但願能幫到還不太清楚的小夥伴,小豬愛大家喲~