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 。
题目比较简单直接,但是 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
的计算。
为了更快速查找数组中严格大于某个值的数量,
- 先对整个数组元素排序,获取它的顺序编号;
- 判断如果将一个元素插入一个数组中,它应该插入的位置,也就是严格大于某个值的数量。而怎么去查找到这个插入的位置:
- 数组有序
- 使用二分查找
完整代码
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;
}
}
题解中使用到了线段树,待学习!!