LeetCode 1787. 使所有区间的异或结果为零

给你一个整数数组 nums​​​ 和一个整数 k​​​​​ 。区间 [left, right](left <= right)的 异或结果 是对下标位于 left 和 right(包括 left 和 right )之间所有元素进行 XOR 运算的结果:nums[left] XOR nums[left+1] XOR … XOR nums[right] 。

返回数组中 要更改的最小元素数 ,以使所有长度为 k 的区间异或结果等于零。

示例 1:

输入:nums = [1,2,0,3,0], k = 1
输出:3
解释:将数组 [1,2,0,3,0] 修改为 [0,0,0,0,0]
示例 2:

输入:nums = [3,4,5,2,1,7,3,4,7], k = 3
输出:3
解释:将数组 [3,4,5,2,1,7,3,4,7] 修改为 [3,4,7,3,4,7,3,4,7]
示例 3:

输入:nums = [1,2,4,1,2,5,1,2,6], k = 3
输出:3
解释:将数组[1,2,4,1,2,5,1,2,6] 修改为 [1,2,3,1,2,3,1,2,3]

提示:

1 <= k <= nums.length <= 2000
​​​​​​0 <= nums[i] < 2 10 2^{10} 210

链接:https://leetcode-cn.com/problems/make-the-xor-of-all-segments-equal-to-zero

思路:动态规划

本题难度较大:
为了使所有长度为 k 的区间异或结果等于零,数组nums 在修改之后是一个以 k 为周期的周期性数组, 即对 ∀ i ∈ [ 0 , n − k ) , n u m s [ i ] = = n u m s [ i + k ] \forall i\in [0,n-k),nums[i]==nums[i+k] i[0,nk),nums[i]==nums[i+k].

这里为了便于复习,记录一下,详细解题思路参见官方题解

下面是题解之一:

class Solution {
public:
    static constexpr int N = 1024; // 2^10
    int minChanges(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> group_amount(k);
        vector<unordered_map<int, int>> group_record(k);
        for(int i = 0; i < n; i++) {
            group_amount[i%k]++;//第k列的元素个数
            group_record[i%k][nums[i]]++;//num[i]在第i%k列出现的次数
        }
            
        vector<vector<int>> dp(k, vector<int>(N));
        for(int j = 0; j < N; j++)
            dp[0][j] = group_amount[0] - group_record[0][j];
        
        for(int i = 1; i < k; i++) {//共k列
            int upper_limit = *min_element(dp[i-1].begin(), dp[i-1].end()) + group_amount[i];
            //上界:第k列所有元素都要更改
            fill(dp[i].begin(), dp[i].end(), upper_limit);

            for(auto [num, amount] : group_record[i])//遍历第k列的元素
                for(int j = 0; j < N; j++)
                    dp[i][j^num] = min(dp[i][j^num], dp[i-1][j] + group_amount[i] - amount);
        }
        return dp[k-1][0];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值