ETH官方钱包

前往
大廳
主題

LeetCode - 1363. Largest Multiple of Three 解題心得

Not In My Back Yard | 2024-08-10 12:00:14 | 巴幣 0 | 人氣 42

題目連結:


題目意譯:
給定一個數字陣列 digits,回傳藉由以任意順序將 digits 中若干個數字串接在一起可以形成的最大 3 的倍數。如果答案不存在,則回傳一個空字串。

由於答案可能無法被容納進整數資料型態中,請以字串形式回傳答案。注意到回傳的答案不得包含不必要的前導零。

限制:
1 ≦ digits.length ≦ 10 ^ 4
0 ≦ digits[i] ≦ 9



範例測資:
範例 1:
輸入: digits = [8,1,9]
輸出: "981"

範例 2:
輸入: digits = [8,6,7,1,0]
輸出: "8760"

範例 3:
輸入: digits = [1]
輸出: ""


解題思維:
首先,一個數字是 3 的倍數若且唯若其各個位數總和可以被 3 整除(參見這題的說明或是其他網路上證明)。

接著把 digits 中的數字根據除以 3 的餘數值分成三類。可以看到餘數為 0 的數字可以直接挑(因為位數總和將會可以被 3 整除)。假設餘數為 1 的數字有 C1 個、餘數為 2 的數字有 C2 個。

可以看到一個餘數 1 的數字和令一個餘數 2 的數字可以互相配對而使得兩數總和可以被 3 整除。因此我們最少可以從 C1 和 C2 個數字中各挑出 m 個數字來配對,其中 m = min(C1, C2)。而為了最終的數字最大化,要挑的數字當然也要盡量地大。

但是也不要忘記三個餘數 1 的數字或是三個餘數 2 的數字可以再形成總和可被 3 整除的數字。因此各自剩下的 C1 - m 和 C2 - m 個數字(注意到根據 m 的定義,有一群會是剩 0 個數字)各自三個三個一組配對。一樣,為了最大化最終的數字,這邊也要盡量挑最大的數字。



不過這樣子有機會會不夠大,因為如果例如說餘數 1 的數字挑完 m 個,且再經過三個三個一組之後還剩 2 個數字。則代表實際上前面挑的 m 個數字多挑了一組,因為我們可以藉由少挑一組來使這邊多湊三個數字一組。因此總計挑的數字數量淨變化量將會是 (-2) + 3 = 1,也就是會多挑一個數字。

而再繼續反悔,總共挑的數字也不會變多。因此最多只會需要反悔一組。當然,這個前提是前面真的有挑數字去配對,意即代表著 m ≧ 1。



將上面的總結來說就是:
    1. 餘數 0 的直接挑。並假設剩下的餘數 1 和餘數 2 的數字各為 C1 和 C2 個。

    2. 令 m = min(C1, C2),代表餘數 1 和餘數 2 要配對的數量。但倘若 m ≧ 1 且「C1 - m 除以 3 的餘數為 2 或是 C2 - m 除以 3 的餘數為 2」,則需要將 m 減 1(以便後面剩下的數字三個三個一組配對)。

    3. 餘數 1 會剩 C1 - m 個數字,餘數 2 會剩 C2 - m 個數字。兩組數字各自三個三個一組配對。最後若還有剩下的數字則無視。

    4. 以上步驟挑的數字都是盡可能地大。

最後把挑的數字由大到小串接在一起即為所求。但是注意,有可能最後挑完只會挑走數字 0(而且可能不只一個 0),因此要額外判斷開頭是不是零。如果是則無視字串長度,直接統一回傳 "0",因為答案不允許前導零。




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

創作回應

更多創作