題目出處
難度
medium
題目分類
Array, Math, Dynamic Programming
2026-09-22 一刷
個人範例程式碼 - 一刷 (2026/09/22)
class Solution:
def resultArray(self, nums: List[int], k: int) -> List[int]:
# since 1 <= k <= 5 is constraint, we can declare the final ans list first
ans = [0] * k
prev_ans = [0] * k # record and update the ans
for num in nums:
# this round
curr_counts = [0] * k
# 1. only me
remainder = num % k
curr_counts[remainder] += 1
# 2. me with prefix
for r in range(k):
if prev_ans[r] > 0:
new_remainder = (r * num) % k # (remain * num) % k = ((origin % k) * num) % k
curr_counts[new_remainder] += prev_ans[r] # all prev_ans with remainder r, add in to curr_counts
# 3. dp update, summarize from nums[0] to current num
# dp only need to remember previous ans (since prefix is consequent)
prev_ans = curr_counts
# summarize this round # from nums[0] to current num
for r in range(k):
ans[r] += curr_counts[r]
return ans
算法說明
這題最難的可能是理解題目
簡單來說就是可以去頭去尾,中間可以任意抓連續值 (數量 >= 1),
然後跟 k 求餘數,計算所有組合的餘數分佈。
例如:[餘數0, 餘數1, …, 餘數k-1] = [統計所有組合餘數為0的數量, 統計所有組合餘數為1的數量, …]
處理時,分成只有單一數值,還有包含前綴的數值,
所以會有幾個步驟
- 處理此數字
- 處理此數字與前面數字的前綴
- 更新前綴 (未來就可以透過前綴餘數,乘上新的值,就可以得到新的餘數結果)
這裡有一個數學式可以證明:(餘數 * 新 num) % k = ((前 num % k) * 新 num) % k
所以我們可以一直拿 mod 後的結果去算就好,不用一直乘上去。
另外關於後綴的部分,後綴的處理已經包含在我們透過處理前綴的過程中,
也就是說當我們掃到該值時,前面的所有組合 (重點在於前一個數字不能斷,要連續) 已經都包含在裡面。
透過儲存前方的結果,以 DP 的方式解決問題。
Time Complexity
O(nk) # n 次掃 nums * k 的填充
Space Complexity
O(k) # 多個 k 作為暫時/最終答案存放