前往
大廳
主題

LeetCode - 368. Largest Divisible Subset 解題心得

Not In My Back Yard | 2022-05-12 12:00:11 | 巴幣 0 | 人氣 338

題目連結:


題目意譯:
給定一相異正整數之集合 nums,回傳最大之子集合 answer 使得其中每對元素 (answer[i], answer[j]) 滿足以下
answer[i] % answer[j] == 0,或
answer[j] % answer[i] == 0

如果有多組解,則回傳任意一種。

限制:
1 ≦ nums.length ≦ 1000
1 ≦ nums[i] ≦ 2 × 10 ^ 9
nums 中的整數皆相異。



範例測資:
範例 1:
輸入: nums = [1,2,3]
輸出: [1,2]
解釋: [1,3] 同樣也可以被接受。

範例 2:
輸入: nums = [1,2,4,8]
輸出: [1,2,4,8]


解題思維:
首先,由於題目沒有限制 i 不得等於 j。因此任何一個只有單一元素的集合即符合題目的條件。

接著把 nums 中的數字由小排到大,這樣我們便只需要考慮 answer[i] % answer[j] == 0 、 answer[j] % answer[i] == 0 其中一個條件即可。



現在定義一陣列 D,其中 D[i] 為在 nums[0] ~ nums[i] 中必須要挑 nums[i] 且符合題目要求的最大集合之大小。則如果現在我們已知 D[0] ~ D[j],則
D[j + 1] = max(1, D[k] + 1)
其中 k ≦ j 且 nums[j + 1] % D[k] == 0。也就是說,要嘛 nums[j + 1] 自己形成一個集合,要嘛與其他可以接的人接在一起。

而一開始我們知道單一元素可以自己形成集合,因此 D[0] = 1(因為只有 nums[0] 自己可以挑)。而後我們便可以依序求出 D[1] 、 D[2] 、……



最後,我們現在知道了答案的「長度」,但是題目要得是「內容」。因此我們需要從長度這個資訊回推出內容。

此時,回顧一下我們對於陣列 D 的定義:D[i] 代表「一定」要挑 nums[i] 進到集合之中。假設 L 是我們求出的最長集合之長度,因此我們可以去找找看哪個 D[i] 之值 == L,而 nums[i] 將會在答案之中;然後我們去看哪個 D[i'] 之值 == L - 1,則 nums[i'] 也會在集合中……以此類推。

可是如果有多組可行解怎麼辦?這樣就無法保證 nums[i] 與 nums[i'] 等等這樣子的挑法真的滿足題目所求。

此時,我們可以額外記錄一個最大公因數 gcd。一開始挑定 nums[i] 之後,令 gcd = nums[i]。接著當我們遇到多組可能的 nums[i'](即 D[i'] == L - 1)時,我們便使用這個 gcd 作為判斷條件。

因為題目的條件,再加上我們已經先行將 nums 排序了,因此當 gcd 可以被 nums[i'] 整除的時候,便代表 nums[i] 和 nums[i'] 可以在同一集合之中(此時記得將 gcd 之值更新成 nums[i'])。其他元素以此類推。

以此,便可以得出所求集合。




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

創作回應

更多創作