欢迎大家加QQ群:623375442,可以方便群里面交流。

100589. Transform Array by Parity

给你一个整数数组 nums。请你按照以下顺序 依次 执行操作,转换 nums:

  1. 将每个偶数替换为 0。
  2. 将每个奇数替换为 1。
  3. 按 非递减 顺序排序修改后的数组。

执行完这些操作后,返回结果数组。

测试样例:

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

输出:[0,0,1,1]

解释:

  • 将偶数(4 和 2)替换为 0,将奇数(3 和 1)替换为 1。现在,nums = [0, 1, 0, 1]。
  • 按非递减顺序排序 nums,得到 nums = [0, 0, 1, 1]。

解答:为了写得快,直接排序了。最好是计算一个0的个数。

class Solution {
    public int[] transformArray(int[] nums) {
        for (int i = 0; i < nums.length; ++i) {
            nums[i] = nums[i] % 2;
        }
        Arrays.sort(nums);
        return nums;
    }
}

100595. Find the Number of Copy Arrays

给你一个长度为 n 的数组 original 和一个长度为 n x 2 的二维数组 bounds,其中 bounds[i] = [ui, vi]。

你需要找到长度为 n 且满足以下条件的 可能的 数组 copy 的数量:

  1. 对于 1 <= i <= n - 1 ,都有 (copy[i] - copy[i - 1]) == (original[i] - original[i - 1]) 。
  2. 对于 0 <= i <= n - 1 ,都有 ui <= copy[i] <= vi 。

返回满足这些条件的数组数目。

测试样例:

输入:original = [1,2,3,4], bounds = [[1,2],[2,3],[3,4],[4,5]]

输出:2

解释:可能的数组为:

  • [1, 2, 3, 4]
  • [2, 3, 4, 5]

解答:计算重叠区域

class Solution {
    public int countArrays(int[] original, int[][] bounds) {
        int[] mark = bounds[0];
        for (int i = 1; i < original.length; ++i) {
            int diff = original[i] - original[i - 1];
            mark[0] += diff;
            mark[1] += diff;
            if (mark[1] < bounds[i][0] || bounds[i][1] < mark[0]) {
                return 0;
            } else {
                mark[0] = Math.max(mark[0], bounds[i][0]);
                mark[1] = Math.min(mark[1], bounds[i][1]);
            }
        }
        return mark[1] - mark[0] + 1;
    }
}

100587. Find Minimum Cost to Remove Array Elements

给你一个整数数组 nums。你的任务是在每一步中执行以下操作之一,直到 nums 为空,从而移除 所有元素 :

  • 从 nums 的前三个元素中选择任意两个元素并移除它们。此操作的成本为移除的两个元素中的 最大值 。
  • 如果 nums 中剩下的元素少于三个,则一次性移除所有剩余元素。此操作的成本为剩余元素中的 最大值 。

返回移除所有元素所需的最小成本。

测试样例:

输入:nums = [6,2,8,4]

输出:12

解释:初始时,nums = [6, 2, 8, 4]。

  • 在第一次操作中,移除 nums[0] = 6 和 nums[2] = 8,操作成本为 max(6, 8) = 8。现在,nums = [2, 4]。
  • 在第二次操作中,移除剩余元素,操作成本为 max(2, 4) = 4。

移除所有元素的成本为 8 + 4 = 12。这是移除 nums 中所有元素的最小成本。所以输出 12。

解答:动态规划,直接计算保留某个数的情况下,最小成本。

class Solution {
    public int minCost(int[] nums) {
        if (nums.length == 1) return nums[0];
        else if (nums.length == 2) return Math.max(nums[0], nums[1]);
        int[] cur = {0};
        for (int i = 1; i < nums.length && i + 1 < nums.length; i = i + 2) {
            int[] next = new int[i + 2];
            Arrays.fill(next, Integer.MAX_VALUE);
            for (int j = 0; j < i; ++j) {
                next[j] = Math.min(next[j], cur[j] + Math.max(nums[i], nums[i + 1]));
                next[i] = Math.min(next[i], cur[j] + Math.max(nums[j], nums[i + 1]));
                next[i + 1] = Math.min(next[i + 1], cur[j] + Math.max(nums[j], nums[i]));
            }
            cur = next;
        }
        if (nums.length % 2 == 0) {
            int last = nums[nums.length - 1];
            int res = Integer.MAX_VALUE;
            for (int i = 0; i < cur.length; ++i) {
                res = Math.min(cur[i] + Math.max(nums[i], last), res);
            }
            return res;
        } else {
            int res = Integer.MAX_VALUE;
            for (int i = 0; i < cur.length; ++i) {
                res = Math.min(cur[i] + nums[i], res);
            }
            return res;
        }
    }
}

100593. Permutations IV

给你两个整数 n 和 k,一个 交替排列 是前 n 个正整数的排列,且任意相邻 两个 元素不都为奇数或都为偶数。

返回第 k 个 交替排列 ,并按 字典序 排序。如果有效的 交替排列 少于 k 个,则返回一个空列表。

测试样例:

输入:n = 4, k = 6

输出:[3,4,1,2]

解答:有点类似数位数组的逻辑,看能不能填入数字

class Solution {
    private static final int[] failed = {};

    public int[] permute(int n, long k) {
        int[] res = new int[n];
        boolean[] isUsed = new boolean[n + 1];
        int odd = (n - 1) / 2 + 1, even = n / 2;
        int last = 0;
        for (int i = 0; i < n; ++i) {
            last ^= 1;
            if (i == 0 && odd == even) {
                long calculate = removeOneOff(k, odd - 1, even);
                for (int j = 1; j <= n; ++j) {
                    if (k <= calculate) {
                        res[i] = j;
                        if (res[i] % 2 == 0) {
                            even -= 1;
                        } else {
                            odd -= 1;
                        }
                        isUsed[j] = true;
                        last = res[0] % 2;
                        break;
                    } else {
                        k -= calculate;
                    }
                }
            } else {
                int start;
                if (last == 0) {
                    start = 2;
                    even -= 1;
                } else {
                    start = 1;
                    odd -= 1;
                }
                long calculate = removeOneOff(k, odd, even);
                for (int j = start; j <= n; j += 2) {
                    if (!isUsed[j]) {
                        if (k <= calculate) {
                            res[i] = j;
                            isUsed[j] = true;
                            break;
                        } else {
                            k -= calculate;
                        }
                    }
                }
            }
            if (res[i] == 0) return failed;
        }
        return res;
    }

    private long removeOneOff(long k, int first, int second) {
        long cur = 1;
        int total = first + second;
        for (int i = 0; i < total; ++i) {
            if (i % 2 == 0 && first != 0) {
                cur *= first;
                first--;
            } else if (i % 2 == 1 && second != 0) {
                cur *= second;
                second--;
            }
            if (cur > k) {
                return cur;
            }
        }
        return cur;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *