題目連結:
題目意譯:
你被給定一個由正整數組成的陣列 nums。
如果在一個子陣列中每一對位於相異位置的元素對按位元 AND (Bitwise AND)後的結果都等於 0 的話,則我們將稱該子陣列為「超讚」。
回傳最長的超讚子陣列之長度。
一個子陣列為一陣列中的連續部分。
注意到長度 1 的子陣列永遠視為超讚。
限制:
1 ≦ nums.length ≦ 10 ^ 5
1 ≦ nums[i] ≦ 10 ^ 9
範例測資:
範例 1:
輸入: nums = [1,3,8,48,10]
輸出: 3
解釋: 最長的超讚子陣列為 [3,8,48]。這個子陣列滿足以下條件:
- 3 AND 8 = 0。
- 3 AND 48 = 0。
- 8 AND 48 = 0。
可以證明沒有更長的超讚子陣列存在,所以我們回傳 3。
範例 2:
輸入: nums = [3,1,5,11,13]
輸出: 1
解釋: 最長的超讚子陣列之長度為 1。任意一個長度 1 的子陣列都可以選。
解題思維:
典型的滑動視窗(Sliding Window)之題型,如
這題。
假設現在知道以位置 i 作為子陣列結尾,最左可以延伸到 x 使得 nums[x] ~ nums[i] 是一個超讚子陣列。則要推得以位置 i + 1,最左可以延伸到何處(稱其為 x')則很單純。
可以看到 x' 不可能小於 x,因為對於 nums[i] 來說就已經只能到 nums[x] 而已。多加一個 nums[i + 1] 只有可能把能延伸到的位置往右移動。
因為 nums[x] ~ nums[i] 是一個超讚子陣列,根據定義子陣列中每一對數字按位元 AND 之結果皆為 0。因此我們定義一值 mask,其為「所有數字」按位元 OR 之結果,而因為是超讚子陣列,所以 mask 中每一個是 1 的位元只會來自於子陣列中恰好一個數字。
而如果加入 nums[i + 1] 後,nums[i + 1] 與 mask 進行按位元 AND 後得到的結果不是 0,則代表 nums[x] ~ nums[i + 1] 不是一個超讚子陣列。
再加上 x' 必定大於等於 x,所以我們可以試著把 x 往右移動,也就是試試看 nums[x + 1] ~ nums[i] 的 mask 之值與 nums[i + 1] 按位元 AND 的結果是否為 0。如果依舊不是 0 就繼續重複此步驟直到是為止。
此時的 x 值正是我們要找的 x' 之值。將此時的 mask 之值與 nums[i + 1] 按位元 OR 之後便可以繼續用來求下一個位置 i + 2 的答案,以此類推。
而過程中,所有的位置 i 與它們對應的 x 值相減再加 1 便可以得到以位置 i 作為結尾的最長超讚子陣列之長度。取這些長度值之中的最大值即為所求。
此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。