首先,我們觀察到條件 (a+b)(modk)=s 只跟 a(modk) 和 b(modk) 有關,而與 a 和 b 的原始數值無關。因此,我們可以先對 nums 陣列中的所有數字進行預處理,將它們全部轉換為模 k 的餘數。這可以大大簡化後續的計算。
方法一:枚舉子序列中相鄰兩項的和 s
這道題要求我們找出一個最長的子序列,使得子序列中任意相鄰兩項的和,在模 k 意義下都是一個定值。
由於這個定值是多少我們事先並不知道,一個直觀的想法是枚舉所有可能的定值。令這個定值為 s,其中 s 的可能範圍是 0,1,…,k−1。對於每一個固定的 s,求解滿足 (sub[i-1] + sub[i]) % k == s 的最長子序列長度。最後,取所有 s 對應的最長長度中的最大值,即為本題的答案。
接下來的問題是,對於一個固定的 s,如何找出最長的有效子序列?這是一個典型的 動態規劃(Dynamic Programming) 問題。我們可以定義一個大小為 (n+1)×k 的 DP 陣列 f,其中 f[i][j] 表示考慮前 i 個數,任兩項和為 s 時,最後一項模 k 為 j 時的最大長度。
當我們遍歷 nums 陣列中的每一個元素 x = nums[i] 時,可以透過 選或不選 x 來更新 f:
如果我們要將 x 作為有效子序列的最新一項,那麼它的前一項 prev 必須滿足 (prev+x)(modk)=s。
值得注意的是,由於子序列中一定是 x,y,⋯,x,y 交錯,因此在 選或不選 nums[i] 的兩種情況中,選一定不會比不選差。這是因為如果在上一個 y 之後、當前的 x 之前,有出現其他的 x′,則此時 f[x] 的值已經且最多是 f[y]+1;如果沒有,則選當前的 x 一定能得到更優的結果,可以用反證法證明。因此選 x 一定不會比不選差。
複雜度分析
時間複雜度:O(k×(k+n))
空間複雜度:O(k)
1 2 3 4 5 6 7 8 9 10 11 12 13
fmax = lambda x, y: x if x > y else y classSolution: defmaximumLength(self, nums: List[int], k: int) -> int: nums[:] = [x % k for x in nums] ans = 0 # 枚舉 (sub[0] + sub[1]) % k 的值 for s inrange(k): f = [0] * k for x in nums: # f[x] = fmax(f[x], f[(s - x) % k] + 1) # 選或不選 nums[i] f[x] = f[(s - x) % k] + 1# 但選了一定不會比不選差 ans = fmax(ans, max(f)) return ans
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include<ranges> classSolution { public: intmaximumLength(vector<int>& nums, int k){ auto arr = nums | views::transform([k](int x) { return x % k; }); int ans = 0; for (int s = 0; s < k; ++s) { vector<int> f(k, 0); for (int x : arr) f[x] = f[(s - x + k) % k] + 1; ans = max(ans, ranges::max(f)); } return ans; } };
classSolution: defmaximumLength(self, nums: List[int], k: int) -> int: f = [[0] * k for _ inrange(k)] for x inmap(lambda x: x % k, nums): for y inrange(k): f[y][x] = f[x][y] + 1 returnmax(map(max, f))
1 2 3 4 5 6 7 8 9 10 11
#include<ranges> classSolution { public: intmaximumLength(vector<int>& nums, int k){ vector<vector<int>> f(k, vector<int>(k, 0)); for (int x : nums | views::transform([k](int x) { return x % k; })) for (int y = 0; y < k; ++y) f[y][x] = f[x][y] + 1; return ranges::max(f | views::transform(ranges::max)); } };
寫在最後
PROMPT
masterpiece, best quality, high quality, extremely detailed CG unity 8k wallpaper, extremely detailed, High Detail, perfect hands, vibrant colors, anime style, cover art, illustration, depth of field, sharp focus, impactful picture, official art, (chocoan:0.5), (mika Pikazo:0.4), (artist: sheya:0.5), (wlop:0.4),
1girl, solo, Lillie, lillie (pokemon), green eyes, long hair, blonde hair, blunt bangs, twin braids, white sun hat, hat, white hat, white dress, sun hat, sleeveless dress, collared dress, contrast collar, round collar, standing outdoors, leaning casually against a wooden railing, wind blowing her hair and dress, expansive grassy field and ocean in the background, wind turbines in the distance, clear blue sky, bright sunlight, relaxed and breezy atmosphere,
Lillie stands gracefully by a wooden fence overlooking a vibrant green field and the sparkling ocean, with wind turbines spinning gently in the distance under a wide, clear blue sky. The sunlight dances across her white dress and sun hat as the breeze stirs her hair, creating a serene and refreshing coastal scene.