Leetcode LCP 14. 切分數組

https://leetcode.cn/problems/qie-fen-shu-zu/description/

給定一個整數數組 nums ,小李想將 nums
切割成若干個非空子數組,使得每個子數組最左邊的數和最右邊的數的最大公約數大於 1 。
爲了減少他的工作量,請求出最少可以切成多少個子數組。

示例 1:

輸入:nums = [2,3,3,2,3,3]

輸出:2

解釋:最優切割爲 [2,3,3,2] 和 [3,3] 。第一個子數組頭尾數字的最大公約數爲 2
,第二個子數組頭尾數字的最大公約數爲 3 。

示例 2:

輸入:nums = [2,3,5,7]

輸出:4

解釋:只有一種可行的切割:[2], [3], [5], [7]

限制:

1 <= nums.length <= 10^5
2 <= nums[i] <= 10^6

解答
1 首先想到動態規劃轉移方程
dp[x]爲索引x 可以分成的最小組數
dp[i] = dp[j-1]+1; == 如果nums[i] nums[j]最大公約數不爲1(用其他質因數) 那麼nums[i] nums[j]劃分爲一組。

2 但是上面的時間複雜度是O(n^2)
優化爲 判斷dp[i]的時候 記錄前邊和他有相同質因數的nums[j]最小分成組數
dp[i] = min(PrimesMinLen[primesV]+1);
分解質因數爲sqrt(x);
時間複雜度爲O(n *sqrt(x))

class Solution {
public:
    int dp[100010];
    unordered_map<int ,int> PrimesMinLen;

    int splitArray(vector<int>& nums) {
        memset(dp, 0x3f, sizeof dp);
        //拆入一個質數 不可能和其他數 分組。  後面索引從1開始計算 避免一些邊界問題
        nums.insert(nums.begin(), 100019);
        dp[0] = 0;
        for (int i = 1; i < nums.size(); i++) {
            dp[i] = dp[i - 1] + 1;  //另開一個數組
            //分解質因數
            int splitP[20]; memset(splitP, 0, sizeof splitP);
            int splitCnt = 0;
            for (int j = 2; j <= nums[i] / j; j++) {
                while (nums[i] % j == 0) {
                    nums[i] /= j;
                    splitP[splitCnt] = j;
                }
                if (splitP[splitCnt] != 0) {
                    int primesV = splitP[splitCnt]; splitCnt++;
                    if (PrimesMinLen.count(primesV) != 0)
                        dp[i] = min(dp[i], PrimesMinLen[primesV]+1);
                }
            }

            if (nums[i] != 1) {   
                splitP[splitCnt] = nums[i]; splitCnt++;
                int primesV = nums[i];
                if(PrimesMinLen.count(primesV) !=0)
                    dp[i] = min(dp[i], PrimesMinLen[primesV]+1);
            }
           
            //更新 該元素左端的元素 質數對應的最短分組
            for (int j = 0; j < splitCnt; j++) {
                int primesV = splitP[j];
                if (PrimesMinLen.count(primesV) == 0) PrimesMinLen[primesV] = dp[i-1];
                else PrimesMinLen[primesV] = min(PrimesMinLen[primesV], dp[i-1]);
            }
        }

        return dp[nums.size() - 1];
    }
};

我的視頻題解空間

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章