Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leetcode 2449. Minimum Number of Operations to Make Arrays Similar #193

Open
Woodyiiiiiii opened this issue Jan 22, 2023 · 0 comments
Open

Comments

@Woodyiiiiiii
Copy link
Owner

Woodyiiiiiii commented Jan 22, 2023

这是一系列变种题的系列最终hard题目。

题目有:

题目类型是:

  1. 选中数组内任意两点,可以进行某种公式变化
  2. 最后求最少多少步骤达到目标数组

解题关键:

  1. 贪心/排序,找到目标
  2. 计算累加值(正/负差值)得出步骤答案

那么先看1551题,第一题要用贪心思想,找到中间值,然后累加步数即可。

class Solution {
    public int minOperations(int n) {
        int target = n % 2 == 0 ? 2 * (n / 2 - 1) + 2 : 2 * (n / 2) + 1;
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            int num = 2 * i + 1;
            ans += Math.abs(target - num);
        }
        return ans / 2;
    }
}

再看2541题,这是双周赛96的第二题,我WA了3次才过,有点不应该了。这题不难,主要是要仔细耐心,注意细节。如下:

  1. 判断。首先审题,数组内元素不能移动;接着判断能否通过变化变成目标数组,一是看差值能否被整除,接着看正负差值之和是否为0
  2. 数值范围。注意到除数k可以为0的,所以取余的时候是无意义的,这时要多加一个判断
  3. 记录总操作数。要想到即然能够通过变化得到目标数组,而且正负差值和为0,相当于无数个k在其中转移,那么直接一步将总的正差值或者负差值作为答案
class Solution {
    public long minOperations(int[] nums1, int[] nums2, int k) {
        int n = nums1.length;
        long diffSum = 0;
        long negativeDiffSum = 0;
        long ans = 0;
        for (int i = 0; i < n; i++) {
            int diff = nums1[i] - nums2[i];
            if (diff == 0) {
                continue;
            }
            if (k == 0) {
                return -1;
            }
            if (diff % k != 0) {
                return -1;
            }
            diff /= k;
            if (diff < 0) {
                negativeDiffSum += diff;
            }
            diffSum += diff;
        }
        if (diffSum != 0) {
            return -1;
        }
        return -negativeDiffSum;
    }
}

来到最后一题2449。

观察条件,我们可以得到很有意思的点,这些都是破题的关键:

  1. 对数组内元素选择两个不同的索引,然后对元素+2或者-2,为什么是2?有什么特别?
  2. 参数保证了一定能通过转换达到target数组
  3. 两数组相等的条件是出现次数相同,而不是顺序相同

如果能彻底理解以上三点,就能够得出题解了。

思路:首先,我们要找到每个元素变换的目标,也就是能够变化达到的距离最近的目标;又因为题目保证了变化能够达到,所以我们不用担心找不到两个对应的索引能够互相成就变化达到各自的目标;那么如何寻找各自的目标呢?需要分组排序。我们通过条件1,可以知道要分成奇偶两组 ,然后对两组从小到大排序,就可以找到两组内每个元素对应的目标了;最后,根据上一题的思路,我们只需要记录正差值或者负差值作为答案即可。

class Solution {
    public long makeSimilar(int[] nums, int[] target) {
        List<Integer> evenList = new ArrayList<>(), oddList = new ArrayList<>();
        Arrays.sort(nums);
        Arrays.sort(target);
        for (int num : nums) {
            if (num % 2 == 0) {
                evenList.add(num);
            } else {
                oddList.add(num);
            }
        }

        int evenIndex = 0, oddIndex = 0;
        long ans = 0;
        for (int t : target) {
            long op = t % 2 == 0 ? (evenList.get(evenIndex++) - t) / 2 : (oddList.get(oddIndex++) - t) / 2;
            ans += op > 0 ? op : 0;
        }

        return ans;
    }
}

这道题难点在于:

  1. 分组
  2. 排序
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant