1. 程式人生 > >【LeetCode】898. Bitwise ORs of Subarrays 解題報告(Python)

【LeetCode】898. Bitwise ORs of Subarrays 解題報告(Python)

目錄

題目描述

We have an array A of non-negative integers.

For every (contiguous) subarray B = [A[i], A[i+1], ..., A[j]] (with i <= j), we take the bitwise OR of all the elements in B, obtaining a result A[i] | A[i+1] | ... | A[j].

Return the number of possible results. (Results that occur more than once are only counted once in the final answer.)

Example 1:

Input: [0]
Output: 1
Explanation: 
There is only one possible result: 0.

Example 2:

Input: [1,1,2]
Output: 3
Explanation: 
The possible subarrays are [1], [1], [2], [1, 1], [1, 2], [1, 1, 2].
These yield the results 1, 1, 2, 1, 3, 3.
There are 3 unique values, so the answer is 3.

Example 3:

Input: [1,2,4]
Output: 6
Explanation: 
The possible results are 1, 2, 3, 4, 6, and 7.

Note:

  1. 1 <= A.length <= 50000
  2. 0 <= A[i] <= 10^9

題目大意

一個數組的所有子陣列的異或結果,總共有多少個不同?

解題方法

動態規劃

題目不是一般的難啊,如果是普通的DP方法,那麼使用二維dp[i][j]表示子陣列的起始和結束區間,能做到O(n^2)的時間複雜度,但是題目對時間複雜度要求的很死,必須O(N).

正確的做法也是動態規劃,dp[i]表示以A[i]結尾的所有子陣列的異或結果,其實是個set。

轉移方程式dp[i] = [b | A[i] for b in dp[i - 1]] + A[i],即以A[i]結尾的所有子陣列異或結果等於以A[i-1]結尾的所有子陣列異或結果,和當前的A[i]異或,再加上A[i]這個結果。

同時使用一個set儲存所有的異或結果。最後返回這個結果set的長度。

此處輸入圖片的描述

dp[i]的大小至多是32個,即 |dp[i]| <= 32 的證明:

dp[i] = {A[i], A[i] | A[i - 1], A[i] | A[i - 1] | A[i - 2], … , A[i] | A[i - 1] | … | A[0]},這個序列單調遞增,通過把A[i]中的0變成1。A[i]最多有32個0。所以這個集合的大小 <= 32。

舉例:最壞情況 A = [8, 4, 2, 1, 0] 都是2^k。 A[5] = 0,dp[5] = {0, 0 | 1, 0 | 1 | 2, 0 | 1 | 2 | 4, 0 | 1 | 2 | 4 | 8} = {0, 1, 3, 7, 15}.

時間複雜度是O(32*N),空間複雜度是O(32N).

class Solution(object):
    def subarrayBitwiseORs(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        res = set()
        cur = set()
        for a in A:
            cur = {n | a for n in cur} | {a}
            res |= cur
        return len(res)

相似題目

參考資料

日期

2018 年 10 月 28 日 —— 10月份最後一個週一