Day 13:3072. 将元素分配到两个数组中 Ⅱ

Leetcode 3072. 将元素分配到两个数组中 Ⅱ

给你一个下标从 1 开始、长度为 n 的整数数组 nums 。

现定义函数 greaterCount ,使得 greaterCount(arr, val) 返回数组 arr 中** 严格大于** val 的元素数量。

你需要使用 n 次操作,将 nums 的所有元素分配到两个数组 arr1 和 arr2 中。在第一次操作中,将 nums[1] 追加到 arr1 。在第二次操作中,将 nums[2] 追加到 arr2 。之后,在第 i 次操作中:

  • 如果 greaterCount(arr1, nums[i]) > greaterCount(arr2, nums[i]) ,将 nums[i] 追加到 arr1 。
  • 如果 greaterCount(arr1, nums[i]) < greaterCount(arr2, nums[i]) ,将 nums[i] 追加到 arr2 。
  • 如果 greaterCount(arr1, nums[i]) == greaterCount(arr2, nums[i]) ,将 nums[i] 追加到元素数量较少的数组中。
  • 如果仍然相等,那么将 nums[i] 追加到 arr1 。

连接数组 arr1 和 arr2 形成数组 result 。例如,如果 arr1 == [1,2,3] 且 arr2 == [4,5,6] ,那么 result = [1,2,3,4,5,6] 。

返回整数数组 result 。

image.png

题目比较简单直接,但是 greaterCount(arr, va) 的计算比较浪费时间,因此不出意外的会超出时间限制。

完整代码

class Solution {
    public int[] resultArray(int[] nums) {
        int n = nums.length;
        List<Integer> arr1 = new ArrayList<>();
        List<Integer> arr2 = new ArrayList<>();
        arr1.add(nums[0]);
        arr2.add(nums[1]);
        for (int i = 2; i < n; i++) {
            int count1 = greaterCount(arr1, nums[i]);
            int count2 = greaterCount(arr2, nums[i]);
            if ((count1 > count2) || ((count1 == count2) && arr1.size() <= arr2.size())) {
                arr1.add(nums[i]);
            } else {
                arr2.add(nums[i]);
            }
        }
        arr1.addAll(arr2);
        for (int i = 0; i < n; i++) {
            nums[i] = arr1.get(i);
        }

        return nums;
    }

    public int greaterCount(List<Integer> arr, int val) {
        int count = 0;
        for (int num : arr) {
            if (num > val) count++;
        }
        return count;
    }
}

需要优化 greaterCount的计算。
为了更快速查找数组中严格大于某个值的数量,

  1. 先对整个数组元素排序,获取它的顺序编号;
  2. 判断如果将一个元素插入一个数组中,它应该插入的位置,也就是严格大于某个值的数量。而怎么去查找到这个插入的位置:
    1. 数组有序
    2. 使用二分查找

完整代码

class Solution {
    public int[] resultArray(int[] nums) {
        int n = nums.length;

        int[] sorted = Arrays.copyOf(nums, n);
        Arrays.sort(sorted);

        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            map.put(sorted[i], i + 1);
        }

        List<Integer> arr1Index = new LinkedList<>();
        List<Integer> arr2Index = new LinkedList<>();

        List<Integer> arr1 = new ArrayList<>();
        List<Integer> arr2 = new ArrayList<>();
        arr1.add(nums[0]);
        arr2.add(nums[1]);

        arr1Index.add(map.get(nums[0]));
        arr2Index.add(map.get(nums[1]));

        for (int i = 2; i < n; i++) {
            if (whichArr(arr1Index, arr2Index, map.get(nums[i])) == 1) {
                arr1.add(nums[i]);
            } else {
                arr2.add(nums[i]);
            }
        }
        
        arr1.addAll(arr2);
        for (int i = 0; i < n; i++) {
            nums[i] = arr1.get(i);
        }

        return nums;
    }

    public int whichArr(List<Integer> index1, List<Integer> index2, int val) {
        int place1 = binaryFind(index1, val);
        int place2 = binaryFind(index2, val);
        int tmp1 = index1.size() - place1;
        int tmp2 = index2.size() - place2;
        if ((tmp1 > tmp2) || ((tmp1 == tmp2 && index1.size() <= index2.size()))) {
            index1.add(place1, val);
            return 1;
        } else {
            index2.add(place2, val);
            return 2;
        }
    }

    public int binaryFind(List<Integer> index, int val) {
        int l = 0, r = index.size() - 1;
        while (l < r) {
            int mid = (r - l) / 2 + l;
            int num = index.get(mid);
            if (val > num) l = mid + 1;
            else if (val < num) r = mid - 1;
            if (val == num) return mid;
        }
        return l;
    }
}

题解中使用到了线段树,待学习!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值