前往
大廳
主題

LeetCode - 1829. Maximum XOR for Each Query 解題心得

Not In My Back Yard | 2024-01-29 12:00:01 | 巴幣 0 | 人氣 50

題目連結:


題目意譯:
你被給定一個有 n 個非負整數且已排序(譯者注:由小排到大)的陣列 nums 以及一整數 maximumBit。你想要執行以下詢問 n 次:
找到一個非負整數 k < 2 ^ maximumBit,使得 nums[0] XOR nums[1] XOR …… XOR nums[nums.length - 1] XOR k 之值是最小的。k 為第 i 筆詢問的答案。
從當前陣列 nums 移除最後一個元素。

回傳一陣列 answer,其中 answer[i] 是第 i 筆詢問的答案。

限制:
nums.length == n
1 ≦ n ≦ 10 ^ 5
1 ≦ maximumBit ≦ 20
0 ≦ nums[i] < 2 ^ maximumBit
nums 按照升序順序排序。



範例測資:
範例 1:
輸入: nums = [0,1,1,3], maximumBit = 2
輸出: [0,3,2,3]
解釋: 詢問之答案為如下:
第 1 筆詢問:nums = [0,1,1,3],k = 0 因為 0 XOR 1 XOR 1 XOR 3 XOR 0 = 3。
第 2 筆詢問:nums = [0,1,1],k = 3 因為 0 XOR 1 XOR 1 XOR 3 = 3。
第 3 筆詢問:nums = [0,1],k = 2 因為 0 XOR 1 XOR 2 = 3。
第 4 筆詢問:nums = [0],k = 3 因為 0 XOR 3 = 3。

範例 2:
輸入: nums = [2,3,4,7], maximumBit = 3
輸出: [5,2,6,5]
解釋: The queries are answered as follows:
第 1 筆詢問:nums = [2,3,4,7],k = 5 因為 2 XOR 3 XOR 4 XOR 7 XOR 5 = 7。
第 2 筆詢問:nums = [2,3,4],k = 2 因為 2 XOR 3 XOR 4 XOR 2 = 7。
第 3 筆詢問:nums = [2,3],k = 6 因為 2 XOR 3 XOR 6 = 7。
第 4 筆詢問:nums = [2],k = 5 因為 2 XOR 5 = 7。

範例 3:
輸入: nums = [0,1,2,2,5,7], maximumBit = 3
輸出: [4,3,6,4,6,7]


解題思維:
可以看到 maximumBit 的條件代表著我們只能動某個 nums[0] XOR nums[1] XOR …… nums[i] 之值(稱此值為 Xi)的最後 maximumBit 位元。在這之前(即這 maximumBit 位元的左側)的所有位元我們是不可能改動的。

再加上 XOR 運算有 x XOR x = 0 的「抵銷」特性(其中 x 可為任意值)。因此為了要最小化 Xi XOR k 之值,我們需要「抵銷」Xi 最後 maximumBit 位元之值。

因此第 i 筆的詢問的答案實際上就是 Xi 最後 maximumBit 位元之值。



接下來就是要如何求每一筆詢問的 Xi 之值。而這可以從左至右掃過 nums,也可以反過來。不過後者就需要除了先前提到的 XOR 之「抵銷」特性以外的另一個特性——對於任意數字 x,滿足 x XOR 0 = x。

而因為範例程式碼是前者,因此:
    可以看到前面定義 Xi 是以 nums[i] 作為基準,而非現在詢問的編號(兩者可不同)。實際上,X0 對應的是最後一筆,X1 是倒數第二筆……以此類推。

    因此我們可以直接從 nums[0] 開始掃過 nums。每一次把先前之 XOR 之值與現在看到的 nums[i] XOR 在一起便可以得到 Xi 之值。而 Xi 實際上對應的是索引值 nums.length - i - 1 之詢問(索引值從 0 開始)。因此 Xi 計算完答案後要把答案放到 answer[nums.length - i - 1] 之位置。




此次分享到此為止,如有任何更加簡潔的想法或是有說明不清楚之地方,也煩請各位大大撥冗討論。

創作回應

更多創作