今天在hdoj上练题,做到了一道离散化加dp加树状数组的题,之前一直没接触过离散化,然后去百度学习了下,在这里总结下,离散化在百科里基本的定义是:
离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
原数据:1,999,100000,15;
处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};
c++的库函数里有lower_bound函数实现了,那在Java中如何进行离散化呢。离散化有两种。
这下面的两种情况代码是我转载这位大佬的https://blog.csdn.net/Viscu/article/details/82631062
第一种:包含重复元素,并且相同元素离散化后也要相同
public class Discretization {
public static int lower_bound(int[] arr,int target){ //找到第一个大于等于x的数的位置
int l=0;
int r=arr.length;
while (l<r){
int mid=l+(r-l)/2;
if(arr[mid]>=target){
r=mid;
}else{
l=mid+1;
}
}
return l==arr.length?-1:l;
}
public static int[] solve(int[] array){
SortedSet<Integer> set=new TreeSet<Integer>();
//利用TreeSet可以同时实现排序和去重 可以代替c++中的unique实现
for(int i=0;i<array.length;++i){
set.add(array[i]);
}
//Integer[] b=(Integer[])set.toArray();
int[] b=new int[set.size()]; //将去重排序的数组赋值给b数组
int ct=0;
for(int cur:set){
b[ct++]=cur;
}
for(int i=0;i<array.length;++i){
array[i]=lower_bound(b,array[i])+1; //利用lower_bound找到该数值的排位(rank)
//排名代表大小 越前越小 越后越大
}
//10000000,2,2,123123213离散化成2,1,1,3
return array;
}
public static void main(String[] args) {
int[] a={10000000,2,2,123123213};
solve(a);
}
}
第二种:1.包含重复元素,并且相同元素离散化后不相同,2.不包含重复元素,并且不同元素离散化后不同
public class Discretization {
static class Node implements Comparable<Node>{
int rt;
int idx;
public Node(int rt, int idx) {
this.rt = rt;
this.idx = idx;
}
@Override
public int compareTo(Node node) {
return rt-node.rt;
}
}
public static void work(int[] array){
int[] rank=new int[array.length];
Node[] nodes=new Node[array.length];
for(int i=0;i<array.length;++i){
nodes[i]=new Node(array[i],i); //传入数值和坐标
}
java.util.Arrays.sort(nodes); //排序 记得实现Comparable接口 以rt大小排序
for(int i=0;i<array.length;++i){
rank[nodes[i].idx]=i;
}
for(int i=0;i<array.length;++i){
array[i]=rank[i]+1;
}
//10000000,2,2,123123213 离散化成 3 1 2 4
}
public static void main(String[] args) {
int[] a={10000000,2,2,123123213};
work(a);
}
}