离散化
去重排序离散化 通过二分查找
public class SetAndMid {
static int[] new_nums;
// 去重以及下标映射
public static void solve(int[] nums){
Map<Integer,Integer> map = new TreeMap<>();
for(var num:nums) map.put(num,1);
int size = map.size();
new_nums = new int[size];
int cnt = 0;
for(int key:map.keySet()) new_nums[cnt ++] = key;
}
// 二分查找对应的 x 的映射下标
public static int find(int x){
return Arrays.binarySearch(new_nums,x);
}
public static void main(String[] args) {
int[] nums = new int[]{1,100,200,300,400,400,400,1000};
solve(nums);
for(int i = 0;i<new_nums.length;i++) System.out.println(i + " " + new_nums[i]);
System.out.println(find(400));
}
}
练习题目:树状数组加离散化
3072. 将元素分配到两个数组中 II - 力扣(LeetCode)
解题代码:
// 树状数组类
class Fenwick{
int[] tree;
Fenwick(int n) {
tree = new int[n];
}
int lowbit(int x){
return x & -x;
}
void add(int x,int u){
for(int i = x;i< tree.length;i += lowbit(i)) tree[i] += u;
}
int query(int x){
int ans = 0;
for(int i = x;i > 0;i -= lowbit(i)) ans += tree[i];
return ans;
}
}
class Solution {
public int[] resultArray(int[] nums) {
int[] sorted = nums.clone();
Arrays.sort(sorted);
int n = nums.length;
List<Integer> l1 = new ArrayList<>(n);
List<Integer> l2 = new ArrayList<>();
l1.add(nums[0]); l2.add(nums[1]);
// System.out.print(nums[0] + " " + nums[1]);
Fenwick t1 = new Fenwick(n + 1);
Fenwick t2 = new Fenwick(n + 1);
// 将初始元素添加到树状数组
t1.add(Arrays.binarySearch(sorted,nums[0]) + 1, 1);
t2.add(Arrays.binarySearch(sorted,nums[1]) + 1, 1);
for(int i = 2;i<n;i++){
int x = nums[i];
int idx = Arrays.binarySearch(sorted,x) + 1;
int a = l1.size() - t1.query(idx);
int b = l2.size() - t2.query(idx);
if(a > b || (a == b && l1.size() <= l2.size())) {
l1.add(x);
t1.add(idx, 1);
}else {
l2.add(x);
t2.add(idx, 1);
}
}
// for(int num:l1) System.out.print(num + " ");
// for(int num:l2) System.out.print(num + " ");
l1.addAll(l2);
int[] ans = new int[n];
int cnt = 0;
for(int num:l1) ans[cnt ++] = num;
return ans;
}
}