【每日一LeetCode】二进制 1 计数 + 差分数组&&前缀和 【区间修改】

144 阅读3分钟

2859. 计算 K 置位下标对应元素的和

class Solution:
    def sumIndicesWithKSetBits(self, nums: List[int], k: int) -> int:
        res = 0
        for i in range(len(nums)):
            if i.bit_count() == k:
                res += nums[i]
        return res

class Solution:
    def sumIndicesWithKSetBits(self, nums: List[int], k: int) -> int:
        return sum(x for i, x in enumerate(nums) if i.bit_count() == k)
class Solution {
public:
    int sumIndicesWithKSetBits(vector<int>& nums, int k) {
        int res = 0;
        for (int i = 0; i < nums.size(); ++i){
            if (__builtin_popcount(i) == k){
                res += nums[i];
            }
        }
        return res;        
    }
};

——————

class Solution:
    def sumIndicesWithKSetBits(self, nums: List[int], k: int) -> int:
        def bitCount(x):
            cnt = 0
            while x:
                cnt += x % 2
                x //= 2
            return cnt 

        return sum(num for i, num in enumerate(nums) if bitCount(i) == k)

2022. 将一维数组转变成二维数组

class Solution:
    def construct2DArray(self, original: List[int], m: int, n: int) -> List[List[int]]:
        if len(original) != n * m:
            return []
        res = [[0] * n for _ in range(m)]
        for i in range(m):
            for j in range(n):
                res[i][j] = original[i * n + j]
        return res 
class Solution:
    def construct2DArray(self, original: List[int], m: int, n: int) -> List[List[int]]:
        return [original[i : i + n] for i in range(0, len(original), n)] if len(original) == m * n else []
class Solution {
public:
    vector<vector<int>> construct2DArray(vector<int>& original, int m, int n) {
        vector<vector<int>> res;
        if (original.size() != m * n){
            return res;
        }
        for (auto it = original.begin(); it != original.end(); it += n){
            res.emplace_back(it, it + n);
        }
        return res;
    }
};

C++ vector 长度 的预定义

class Solution {
public:
    vector<vector<int>> construct2DArray(vector<int>& original, int m, int n) {
        if (original.size() != m * n){
            return {}; // C++ 只有 这种 {}
        }

        vector<vector<int>> res(m, vector<int>(n)); // 注意 这种长度的定义。

        for (int i = 0;  i < m; ++i){
            for (int j = 0; j < n; ++j){
                res[i][j] = original[i * n + j];
            }
        }
        return res;
    }
};

1589. 所有排列中的最大和

前缀和 + 差分 【区间修改】

前缀和: 快速计算 子区间 的和

统计查询次数时:区间内 所有元素 都 加 1。 考虑 用差分

参考链接 image.png

image.png

将 复杂度 从 O(n) 降到 O(1)

image.png

image.png image.png image.png

class Solution:
    def maxSumRangeQuery(self, nums: List[int], requests: List[List[int]]) -> int:
        # 看 交集, 交集 越多, 放 更大的数  直接模拟 超时

        ## 差分  前缀和  查询次数 统计
        n = len(nums)
        counts = [0] * n  # 原始数组 和 差分数组 都是这个
        for start, end in requests:  # 差分 数组 维护
            counts[start] += 1
            if end + 1 < n:
                counts[end + 1] -= 1
        for i in range(1, n):
            counts[i] += counts[i - 1]  # 得到 修改后的 counts

        nums.sort(reverse = True)
        counts.sort(reverse = True)
        res = 0
        for i in range(len(counts)):
            res += nums[i] * counts[i]
        return res % (10**9 + 7)

image.png

class Solution {
public:
    int maxSumRangeQuery(vector<int>& nums, vector<vector<int>>& requests) {
        // 差分 + 前缀和
        int n = nums.size();
        vector<int> counts(n, 0); //注意 这里
        for (auto r : requests){
            int start = r[0], end = r[1];
            counts[start] += 1;
            if (end + 1 < n){
                counts[end + 1] -= 1;
            }
        }
        for (int i = 1; i < n; ++i){
            counts[i] += counts[i - 1];
        }
        long long res = 0;
        sort(nums.begin(), nums.end());
        sort(counts.begin(), counts.end());
        for (int i = n - 1; i >= 0 && counts[i] > 0; --i){
            res += (long long)nums[i] * counts[i];
        } 
        return res % 1000000007;
    }
};

————————————

超时 的模拟做法

class Solution:
    def maxSumRangeQuery(self, nums: List[int], requests: List[List[int]]) -> int:
        # 看 交集, 交集 越多, 放 更大的数
        dic = defaultdict(int)
        for r in requests:
            for r1 in range(r[0], r[1]  + 1):
                dic[r1] += 1
        nums.sort(reverse = True)
        lis = sorted(dic.values(), reverse = True)
        res = 0
        for i in range(len(lis)):
            res += nums[i] * lis[i]
        return res % (10**9 + 7)

1835. 所有数对按位与结果的异或和

class Solution:
    def getXORSum(self, arr1: List[int], arr2: List[int]) -> int:
        return reduce(xor, arr1) & reduce(xor, arr2)
class Solution {
public:
    int getXORSum(vector<int>& arr1, vector<int>& arr2) {
        return accumulate(arr1.begin(), arr1.end(), 0, bit_xor<int>()) & accumulate(arr2.begin(), arr2.end(), 0, bit_xor<int>());

    }
};

image.png