置頂

GeoGebra 文章目錄

GeoGebra 文章目錄  更新日期:2018/2/8 我將 GeoGebra 相關的文章及檔案連結都整理在這篇裡,之後如果有新的文章也會同時更新這個目錄。上傳到 GeoGebraTube 的檔案,我有試著用 Google Chrome 63.0.3239.13...

熱門文章

2026年6月27日 星期六

LeetCode 解題筆記:3020. Find the Maximum Number of Elements in Subset

作者:王一哲
日期:2026年6月27日


LeetCode 題目連結:3020. Find the Maximum Number of Elements in Subset

解題想法


中等難度題。由於題目要從陣列 $nums$ 之中取最多個數字,數字符合 $x, x^2, x^4, ..., x^{n/2}, x^x, x^{n/2}, ..., x^4, x^2, x$ 的關係,因此解題時要先用字典計數,計算各數字的數量。但是題目的數字有點大,如果用 C++ 解題時,key 值需要用 long long 格式,用 int 會溢位。答案 $ans$ 預設為 $1$,因為至少可以取 $1$ 個數字。接下來先處理全部都取 $1$ 的狀況,如果 $1$ 的數量為 $ones$,長度需要取奇數,更新 $ans$。最後依序從計中數器 $cnt$ 之中取出 key 值 $x$,跳過已經檢查過的 $x = 1$;假設 $sq = \sqrt{x}$,如果 $sq$ 在 $cnt$ 之中而且 $cnt[sq] \geq 2$,代表 $x$ 包含在從 $sq$ 開始往上檢查的過程中,可以跳過,稍微節省一點時間。最後用一個 while 迴圈,如果 $cnt[x] \geq 2$ 而且 $x*x$ 在 $cnt$ 之中就繼續執行,並將長度 $length$ 加 1。結束 while 迴圈之後,更新 $ans$,取 $ans$ 及 $length * 2 + 1$ 較大者。

Python 程式碼


Runtime: 87 ms, beats 98.43%. Memory: 31.53 MB, beats 66.93%.
class Solution:
    def maximumLength(self, nums: List[int]) -> int:
        cnt = Counter(nums)  # 每個數字的數量
        ans = 0  # 答案
        # --- 先處理全部都是 1 的特例 ---
        if 1 in cnt:  # 如果 cnt 之中有 1,數量取奇數
            ans = max(ans, cnt[1] - (cnt[1] % 2 == 0))
        # --- 一般狀況 ---
        for x in cnt.keys():
            # 跳過已經檢查過的 1
            if x == 1: continue
            # 如果 isqrt(x) 也在 cnt 之中,x 會包含在從 isqrt(x) 開始的檢查過程中,可以跳過
            sq = isqrt(x)
            if sq > 1 and sq in cnt and cnt[sq] >= 2: continue
            # 從 x 開始往上檢查至 cnt[x] 數量小於 2 或 x*x 不在 cnt 之中或
            length = 0
            while cnt[x] >= 2 and x*x in cnt:
                length += 1
                x *= x
            ans = max(ans, length * 2 + 1)
        return ans


C++ 程式碼


Runtime: 61 ms, beats 84.57%. Memory: 122.86 MB, beats 30.29%.
class Solution {
public:
    int maximumLength(vector<int>& nums) {
        unordered_map<long long, int> cnt;  // 計數器
        for(long long num : nums) cnt[num]++;
        /* 先處理全部都是 1 的特例 */
        int ans = 1;
        if (cnt.count(1) == 1) {
            ans = max(ans, cnt[1] - (cnt[1] % 2 == 0));  // 答案
        }
        /* 一般狀況 */
        for(auto it : cnt) {
            long long x = it.first;
            // 跳過 1,已經處理過
            if (x == 1) continue;
            // sq = (long)sqrt(x),如果 sq > 1 而且 cnt[sq] >= 2,x 包含在從 sq 開始的檢查之中,跳過
            long long sq = round(sqrt(x));
            if (sq*sq == x && cnt.count(sq) == 1 && cnt[sq] >= 2) continue;
            int length = 0;
            long long curr = x;
            while(cnt[curr] >= 2 && cnt.count(curr * curr) == 1) {
                length++;
                curr *= curr;
            }
            ans = max(ans, length * 2 + 1);
        }
        return ans;
        
    }
};


沒有留言:

張貼留言