这周双周赛,我觉得题目不是很好。2,3题都是脑经急转弯,最后一题也过于模版。

6359. Maximum Difference by Remapping a Digit

给你一个整数 num 。你知道 Danny Mittal 会偷偷将 0 到 9 中的一个数字 替换 成另一个数字。

请你返回将 num 中 恰好一个 数字进行替换后,得到的最大值和最小值的差位多少。

注意:

  • 当 Danny 将一个数字 d1 替换成另一个数字 d2 时,Danny 需要将 nums 中所有 d1 都替换成 d2 。
  • Danny 可以将一个数字替换成它自己,也就是说 num 可以不变。
  • Danny 可以将数字分别替换成两个不同的数字分别得到最大值和最小值。
  • 替换后得到的数字可以包含前导 0 。
  • Danny Mittal 获得周赛 326 前 10 名,让我们恭喜他。

测试样例

输入:nums = 11891

输出:99009

解释:

为了得到最大值,我们将数字 1 替换成数字 9 ,得到 99899 。
为了得到最小值,我们将数字 1 替换成数字 0 ,得到 890 。
两个数字的差值为 99009 。

解答:max就是寻找第一个非9的数字,并map为9。min就是把最大位map成0

class Solution {
    public int minMaxDifference(int num) {
        String tmp = String.valueOf(num);
        char map = 0, minMap = tmp.charAt(0);
        for (int i = 0; i < tmp.length(); ++i) {
            if (tmp.charAt(i) != '9') {
                map = tmp.charAt(i);
                break;
            }
        }
        int max = 0, min = 0;
        for (int i = 0; i < tmp.length(); ++i) {
            if (tmp.charAt(i) == map) {
                max = max * 10 + 9;
            } else {
                max = max * 10 + tmp.charAt(i) - '0';
            }
            if (tmp.charAt(i) == minMap) {
                min = min * 10;
            } else {
                min = min * 10 + tmp.charAt(i) - '0';
            }
        }
        return max - min;
    }
}

6361. Minimum Score by Changing Two Elements

给你一个下标从 0 开始的整数数组 nums 。

  • nums 的 最小 得分是满足 0 <= i < j < nums.length 的 |nums[i] - nums[j]| 的最小值。
  • nums的 最大 得分是满足 0 <= i < j < nums.length 的 |nums[i] - nums[j]| 的最大值。
  • nums 的分数是 最大 得分与 最小 得分的和。

我们的目标是最小化 nums 的分数。你 最多 可以修改 nums 中 2 个元素的值。

请你返回修改 nums 中 至多两个 元素的值后,可以得到的 最小分数 。

|x| 表示 x 的绝对值。

测试样例:

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

输出:0

解释:

将 nums[1] 和 nums[2] 的值改为 1 ,nums 变为 [1,1,1] 。|nums[i] - nums[j]| 的值永远为 0 ,所以我们返回 0 + 0 = 0 。

解答: 如果数组长度小于3,直接返回0。

由于最多可以替换2个数,那么min必然可以做到0。重点就是寻找最大的绝对值。其实也很简单。排序之后,我们可以找到最大值和最小值。那么最优的策略就是替换队头或者队尾或者队头队尾各替换一个,就能找到最小的最大绝对差值。

代码没有优化到最佳,直接使用了排序。

class Solution {
    public int minimizeSum(int[] nums) {
        if (nums.length <= 3) return 0;
        Arrays.sort(nums);
        return Math.min(nums[nums.length - 1] - nums[2], Math.min(nums[nums.length - 3] - nums[0], nums[nums.length - 2] - nums[1]));
    }
}

6360. Minimum Impossible OR

给你一个下标从 0 开始的整数数组 nums 。

如果存在一些整数满足 0 <= index1 < index2 < ... < indexk < nums.length ,得到 nums[index1] | nums[index2] | ... | nums[indexk] = x ,那么我们说 x 是 可表达的 。换言之,如果一个整数能由 nums 的某个子序列的或运算得到,那么它就是可表达的。

请你返回 nums 不可表达的 最小非零整数 。

测试样例:

输入:nums = [2,1]

输出:4

解释:

1 和 2 已经在数组中,因为 nums[0] | nums[1] = 2 | 1 = 3 ,所以 3 是可表达的。由于 4 是不可表达的,所以我们返回 4 。

解答: 这道题又是脑经急转弯。其实本质是寻找第一个不存在的,2的倍数。

可以看看简单的例子:

  • 如果1,2存在,那么小于4的数字必然都能组合出来
  • 如果1,2,4存在,那么小于8的数字都能组合出来
  • 以此类推...
class Solution {
    public int minImpossibleOR(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for (int i : nums) {
            set.add(i);
        }
        for (int i = 1; i < Integer.MAX_VALUE; i = i * 2) {
            if (!set.contains(i)) {
                return i;
            }
        }
        return -1;
    }
}

6358. Handling Sum Queries After Update

给你两个下标从 0 开始的数组 nums1 和 nums2 ,和一个二维数组 queries 表示一些操作。总共有 3 种类型的操作:

  1. 操作类型 1 为 queries[i] = [1, l, r] 。你需要将 nums1 从下标 l 到下标 r 的所有 0 反转成 1 或将 1 反转成 0 。l 和 r 下标都从 0 开始。
    1.操作类型 2 为 queries[i] = [2, p, 0] 。对于 0 <= i < n 中的所有下标,令 nums2[i] = nums2[i] + nums1[i] * p 。
    1.操作类型 3 为 queries[i] = [3, 0, 0] 。求 nums2 中所有元素的和。
    请你返回一个数组,包含所有第三种操作类型的答案。

测试样例:

输入:nums1 = [1,0,1], nums2 = [0,0,0], queries = [[1,1,1],[2,1,0],[3,0,0]]

输出:[3]

解释:

第一个操作后 nums1 变为 [1,1,1] 。第二个操作后,nums2 变成 [1,1,1] ,所以第三个操作的答案为 3 。所以返回 [3] 。

解答:利用惰性传播的线段数的模板题。如果你会惰性传播的线段数,那么稍微换个思路,如果对一个范围内的nums1进行1操作,那么就等于这个范围内长度 - 原始的sum。

操作2,可以通过简单的累和计算得到。

class Solution {
    class LazySegmentTree {
        int MAX;
        int[] tree;
        int[] lazy;
        int len;

        private void updateRangeUtil(int si, int ss, int se, int us,
                                     int ue) {
            if (lazy[si] != 0) {
                tree[si] = (se - ss + 1) - tree[si];

                if (ss != se) {
                    lazy[si * 2 + 1] ^= lazy[si];
                    lazy[si * 2 + 2] ^= lazy[si];
                }
                lazy[si] = 0;
            }

            if (ss > se || ss > ue || se < us)
                return;

            if (ss >= us && se <= ue) {
                tree[si] = (se - ss + 1) - tree[si];

                if (ss != se) {
                    lazy[si * 2 + 1] ^= 1;
                    lazy[si * 2 + 2] ^= 1;
                }
                return;
            }

            int mid = (ss + se) / 2;
            updateRangeUtil(si * 2 + 1, ss, mid, us, ue);
            updateRangeUtil(si * 2 + 2, mid + 1, se, us, ue);

            tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2];
        }

        public void updateRange(int us, int ue) {
            updateRangeUtil(0, 0, len - 1, us, ue);
        }

        private int getSumUtil(int ss, int se, int qs, int qe, int si) {
            if (lazy[si] != 0) {
                tree[si] = (se - ss + 1) - tree[si];

                if (ss != se) {
                    lazy[si * 2 + 1] ^= 1;
                    lazy[si * 2 + 2] ^= 1;
                }

                lazy[si] = 0;
            }

            if (ss > se || ss > qe || se < qs)
                return 0;

            if (ss >= qs && se <= qe)
                return tree[si];

            int mid = (ss + se) / 2;
            return getSumUtil(ss, mid, qs, qe, 2 * si + 1) +
                    getSumUtil(mid + 1, se, qs, qe, 2 * si + 2);
        }

        public int getSum(int qs, int qe) {
            if (qs < 0 || qe > len - 1 || qs > qe) {
                return -1;
            }

            return getSumUtil(0, len - 1, qs, qe, 0);
        }

        private void constructSTUtil(int arr[], int ss, int se, int si) {
            if (ss > se)
                return;

            if (ss == se) {
                tree[si] = arr[ss];
                return;
            }
            int mid = (ss + se) / 2;
            constructSTUtil(arr, ss, mid, si * 2 + 1);
            constructSTUtil(arr, mid + 1, se, si * 2 + 2);

            tree[si] = tree[si * 2 + 1] + tree[si * 2 + 2];
        }

        public void constructST(int[] arr) {
            MAX = findMax(0, arr.length) + 1;
            len = arr.length;
            tree = new int[MAX];
            lazy = new int[MAX];
            constructSTUtil(arr, 0, len - 1, 0);
        }

        private int findMax(int si, int remain) {
            if (remain == 1) {
                return si;
            } else {
                return Math.max(findMax(si * 2 + 1, remain - remain / 2), findMax(si * 2 + 2, remain / 2));
            }
        }
    }

    public long[] handleQuery(int[] nums1, int[] nums2, int[][] queries) {
        LazySegmentTree tree = new LazySegmentTree();
        tree.constructST(nums1);

        long sum = 0;
        for (int n : nums2) {
            sum += n;
        }

        List<Long> res = new ArrayList<>();
        for (int[] q : queries) {
            if (q[0] == 1) {
                tree.updateRange(q[1], q[2]);
            } else if (q[0] == 2) {
                long t = q[1];
                sum = sum + tree.getSum(0, nums1.length - 1) * t;
            } else {
                res.add(sum);
            }
        }

        long[] arr = new long[res.size()];
        for (int i = 0; i < arr.length; ++i) {
            arr[i] = res.get(i);
        }
        return arr;
    }
}

Leave a Reply

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