LeetCode 力扣周赛 255

142 阅读1分钟

传送门

在这里插入图片描述

5850. 找出数组的最大公约数

思路:最大公约数

时间复杂度O(n+lgm)O(n+\lg m)nn 为元素数量,mm 为最大值。

按照题目要求,先找出最大值 aa 和最小值 bb,然后求解两者最大公约数即可。

可用辗转相除法求解最大公约数,该算法的时间复杂度为 O(lgm)O(\lg m)。也可使用库函数 __gcd,代码量更小。

class Solution {
public:
    int findGCD(vector<int>& nums) {
        int a = nums[0], b = nums[0];
        for (auto c : nums) {
            a = min(a, c);
            b = max(b, c);
        }
        return __gcd(a,b);
    }
};

5851. 找出不同的二进制字符串

思路:构造

时间复杂度O(n)O(n)

设有长度为 nn 的字符串 SS。容易做到 SiS_inumsi,inums_{i,i} 不同,取反即可。

这样的 SS 保证了与任意一个 numsinums_i 都至少有一个字符不同,满足题目要求。

class Solution {
public:
    string findDifferentBinaryString(vector<string>& nums) {
        string anw;
        for (int i = 0; i < nums.size(); i++) {
            anw += (nums[i][i] == '0' ? '1' : '0');
        }
        return anw;
    }
};

5852. 最小化目标值与所选元素的差

思路:动态规划

时间复杂度O(mnsum)O(m*n*sum),sum 为 70m70*m

设有二维数组 dpdpdpi,jdp_{i,j} 表示在前 ii 行中选取 ii 个数,其累加和能否为 jj。为了方便描述,令下标从 1 开始。

初始状态 dp0,0dp_{0,0},即从前 0 行中选取了 0 个数,其累加和显然为 0,所以 dp0,0=truedp_{0,0} = true

i>0i \gt 0 时,如果存在 kk 满足 dpi1,jmati,kdp_{i-1,j-mat_{i,k}} 为真,则 dpi,jdp_{i,j} 为真,反之为假。

答案为 min(dpm,itarget),dpm,i=true\min(|dp_{m,i}-target|),dp_{m,i} = true

class Solution {
public:
    bool dp[71][4901] = {0};
    int minimizeTheDifference(vector<vector<int>>& mat, int target) {
        dp[0][0] = true;
        for (int i = 1; i <= mat.size(); i++) {
            for (int j = 0; j <= i*70; j++) {
                if (dp[i-1][j]) {
                    for (int k = 0; k < mat[i-1].size(); k++) {
                        if (j+mat[i-1][k] <= 4900) {
                            dp[i][j+mat[i-1][k]] = true;
                        }
                    }
                }
            }
        }
        int anw = INT_MAX;
        for (int i = 0; i <= 4900; i++) {
            if (dp[mat.size()][i]) {
                anw = min(anw, abs(i-target));
            }
        }
        return anw;
    }
};

5853. 从子集的和还原数组

思路:构造,剪枝

时间复杂度O(max2n)O(max*2^n),max 为取值上限,即 40000。

设答案为长度为 nn 的数组 AA

接下来,开始构造 A0A_0。从 0 开始枚举 dd,如果可将 sumssums 分为等长的两部分 LLRR,并满足 Lj+d=Rjj[0,n2)L_j + d = R_j,j ∈[0,\frac{n}{2})

这可以理解为,一部分中每个数都加了 A0A_0,另一部分都没加 A0A_0

如果 d-d 存在于 LL 中,则 d-d 即为 A0A_0,并更新 sums=Rsums = R,反之 dd 即为 A0A_0,并更新 sums=Lsums = L

重复上述过程,直到构造完成。

class Solution {
public:
    int split(const vector<int> &nums, int val, vector<int> &remain, const unordered_set<int> &mark) {
        vector<int> L, R;
        int pos = 0;

        for (int i = 0; i < nums.size(); i++) {
            if (R.size() <= pos || R[pos] != nums[i]) {
                if (mark.count(nums[i]+val) == 0) {
                    return INT_MAX;
                }
                L.push_back(nums[i]);
                R.push_back(nums[i]+val);
            } else {
                pos++;
            }
        }
        if (L.size() == R.size() && L.size() + R.size() == nums.size()) {
            /*
            cout << "L: ";
            for (auto c : L) {
                cout << c << " ";
            }
            cout << endl << "R: ";
            for (auto c : R) {
                cout << c << " ";
            }
            cout << endl;
            */
            if (std::find(L.begin(), L.end(), -val) != L.end()) {
                std::swap(R, remain);
                return -val;
            }
            std::swap(L, remain);
            return val;
        }
        return INT_MAX;
    }
    vector<int> recoverArray(int n, vector<int>& sums) {
        sort(sums.begin(), sums.end());
        auto nums = sums;
        vector<int> anw;
        unordered_set<int> mark;
        for_each(nums.begin(), nums.end(), [&mark] (int x) {mark.insert(x);});
        while(anw.size() < n) {
            for (int i = 0; i <= 40000; i++) {
                int tmp = split(nums, i, nums, mark);
                if (tmp != INT_MAX) {
                    mark.clear();
                    for_each(nums.begin(), nums.end(), [&mark] (int x) {mark.insert(x);});
                    anw.push_back(tmp);
                    break;
                }
            }
        }
        return anw;
    }
};