列表

详情


100365. 使差值相等的最少数组改动次数

给你一个长度为 n 的整数数组 nums ,n 是 偶数 ,同时给你一个整数 k 。

你可以对数组进行一些操作。每次操作中,你可以将数组中 任一 元素替换为 0 到 k 之间的 任一 整数。

执行完所有操作以后,你需要确保最后得到的数组满足以下条件:

请你返回满足以上条件 最少 修改次数。

 

示例 1:

输入:nums = [1,0,1,2,4,3], k = 4

输出:2

解释:
我们可以执行以下操作:

整数 X 为 2 。

示例 2:

输入:nums = [0,1,2,3,3,6,5,4], k = 6

输出:2

解释:
我们可以执行以下操作:

整数 X 为 4 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int minChanges(vector<int>& nums, int k) { } };

python3 解法, 执行用时: 215 ms, 内存消耗: 28 MB, 提交时间: 2024-07-23 22:12:19

class Solution:
    def minChanges(self, nums: List[int], k: int) -> int:
        n = len(nums)
        d = [0] * (k + 2)
        for i in range(n // 2):
            p, q = nums[i], nums[n - 1 - i]
            if p > q:  # 保证 p <= q
                p, q = q, p
            x = q - p
            mx = max(q, k - p)
            # [0, x-1] 全部 +1:把 q-p 改成小于 x 的,只需要改 p 或 q 中的一个数
            d[0] += 1
            d[x] -= 1
            # [x+1, mx] 全部 +1:把 q-p 改成大于 x 小于等于 mx 的,也只需要改 p 或 q 中的一个数
            d[x + 1] += 1
            d[mx + 1] -= 1
            # [mx+1, k] 全部 +2:把 q-p 改成大于 mx 的,p 和 q 都需要改
            d[mx + 1] += 2
        return min(accumulate(d))

    def minChanges2(self, nums: List[int], k: int) -> int:
        cnt = [0] * (k + 1)
        cnt2 = [0] * (k + 1)
        n = len(nums)
        for i in range(n // 2):
            p, q = nums[i], nums[n - 1 - i]
            if p > q:  # 保证 p <= q
                p, q = q, p
            cnt[q - p] += 1
            cnt2[max(q, k - p)] += 1

        ans = n
        sum2 = 0  # 统计有多少对 (p,q) 都要改
        for c, c2 in zip(cnt, cnt2):
            # 其他 n/2-c 对 (p,q) 至少要改一个数,在此基础上,有额外的 sum2 对 (p,q) 还要再改一个数
            ans = min(ans, n // 2 - c + sum2)
            # 对于后面的更大的 x,当前的这 c2 对 (p,q) 都要改
            sum2 += c2
        return ans

java 解法, 执行用时: 6 ms, 内存消耗: 59.6 MB, 提交时间: 2024-07-23 22:11:39

class Solution {
    public int minChanges(int[] nums, int k) {
        int[] cnt = new int[k + 1];
        int[] cnt2 = new int[k + 1];
        int n = nums.length;
        for (int i = 0; i < n / 2; i++) {
            int p = nums[i];
            int q = nums[n - 1 - i];
            if (p > q) { // 保证 p <= q
                int tmp = p;
                p = q;
                q = tmp;
            }
            cnt[q - p]++;
            cnt2[Math.max(q, k - p)]++;
        }

        int ans = n;
        int sum2 = 0; // 统计有多少对 (p,q) 都要改
        for (int x = 0; x <= k; x++) {
            // 其他 n/2-cnt[x] 对 (p,q) 至少要改一个数,在此基础上,有额外的 sum2 对 (p,q) 还要再改一个数
            ans = Math.min(ans, n / 2 - cnt[x] + sum2);
            // 对于后面的更大的 x,当前的这 cnt2[x] 对 (p,q) 都要改
            sum2 += cnt2[x];
        }
        return ans;
    }

    public int minChanges2(int[] nums, int k) {
        int n = nums.length;
        int[] d = new int[k + 2];
        for (int i = 0; i < n / 2; i++) {
            int p = nums[i];
            int q = nums[n - 1 - i];
            if (p > q) { // 保证 p <= q
                int tmp = p;
                p = q;
                q = tmp;
            }
            int x = q - p;
            int mx = Math.max(q, k - p);
            // [0, x-1] 全部 +1:把 q-p 改成小于 x 的,只需要改 p 或 q 中的一个数
            d[0]++;
            d[x]--;
            // [x+1, mx] 全部 +1:把 q-p 改成大于 x 小于等于 mx 的,也只需要改 p 或 q 中的一个数
            d[x + 1]++;
            d[mx + 1]--;
            // [mx+1, k] 全部 +2:把 q-p 改成大于 mx 的,p 和 q 都需要改
            d[mx + 1] += 2;
        }

        int ans = n;
        int minModify = 0;
        for (int v : d) {
            minModify += v;
            ans = Math.min(ans, minModify);
        }
        return ans;
    }
}

cpp 解法, 执行用时: 123 ms, 内存消耗: 105 MB, 提交时间: 2024-07-23 22:11:10

class Solution {
public:
    int minChanges(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> d(k + 2);
        for (int i = 0; i < n / 2; i++) {
            int p = nums[i], q = nums[n - 1 - i];
            if (p > q) {  // 保证 p <= q
                swap(p, q);
            }
            int x = q - p;
            int mx = max(q, k - p);
            // [0, x-1] 全部 +1:把 q-p 改成小于 x 的,只需要改 p 或 q 中的一个数
            d[0]++;
            d[x]--;
            // [x+1, mx] 全部 +1:把 q-p 改成大于 x 小于等于 mx 的,也只需要改 p 或 q 中的一个数
            d[x + 1]++;
            d[mx + 1]--;
            // [mx+1, k] 全部 +2:把 q-p 改成大于 mx 的,p 和 q 都需要改
            d[mx + 1] += 2;
        }
        partial_sum(d.begin(), d.end(), d.begin()); // 计算前缀和,得到 minModify 数组
        return ranges::min(d);
    }

    int minChanges2(vector<int>& nums, int k) {
        vector<int> cnt(k + 1), cnt2(k + 1);
        int n = nums.size();
        for (int i = 0; i < n / 2; i++) {
            int p = nums[i], q = nums[n - 1 - i];
            if (p > q) { // 保证 p <= q
                swap(p, q);
            }
            cnt[q - p]++;
            cnt2[max(q, k - p)]++;
        }

        int ans = n;
        int sum2 = 0; // 统计有多少对 (p,q) 都要改
        for (int x = 0; x <= k; x++) {
            // 其他 n/2-cnt[x] 对 (p,q) 至少要改一个数,在此基础上,有额外的 sum2 对 (p,q) 还要再改一个数
            ans = min(ans, n / 2 - cnt[x] + sum2);
            // 对于后面的更大的 x,当前的这 cnt2[x] 对 (p,q) 都要改
            sum2 += cnt2[x];
        }
        return ans;
    }
};

golang 解法, 执行用时: 103 ms, 内存消耗: 9.1 MB, 提交时间: 2024-07-23 22:10:37

// 枚举X
func minChanges(nums []int, k int) int {
	cnt := make([]int, k+1)
	cnt2 := make([]int, k+1)
	n := len(nums)
	for i := 0; i < n/2; i++ {
		p, q := nums[i], nums[n-1-i]
		if p > q { // 保证 p <= q
			p, q = q, p
		}
		cnt[q-p]++
		cnt2[max(q, k-p)]++
	}

	ans := n
	sum2 := 0 // 统计有多少对 (p,q) 都要改
	for x, c := range cnt {
		// 其他 n/2-c 对 (p,q) 至少要改一个数,在此基础上,有额外的 sum2 对 (p,q) 还要再改一个数
		ans = min(ans, n/2-c+sum2)
		// 对于后面的更大的 x,当前的这 cnt2[x] 对 (p,q) 都要改
		sum2 += cnt2[x]
	}
	return ans
}

// 差分数组
func minChanges2(nums []int, k int) int {
	n := len(nums)
	d := make([]int, k+2)
	for i := 0; i < n/2; i++ {
		p, q := nums[i], nums[n-1-i]
		if p > q { // 保证 p <= q
			p, q = q, p
		}
		x := q - p
		mx := max(q, k-p)
		// [0, x-1] 全部 +1:把 q-p 改成小于 x 的,只需要改 p 或 q 中的一个数
		d[0]++
		d[x]--
		// [x+1, mx] 全部 +1:把 q-p 改成大于 x 小于等于 mx 的,也只需要改 p 或 q 中的一个数
		d[x+1]++
		d[mx+1]--
		// [mx+1, k] 全部 +2:把 q-p 改成大于 mx 的,p 和 q 都需要改
		d[mx+1] += 2
	}

	ans := n
	minModify := 0
	for _, v := range d {
		minModify += v
		ans = min(ans, minModify)
	}
	return ans
}

上一题