Java使用stream进行数组离散化

本文介绍了如何使用Java的Stream API进行数组的离散化操作,结合二分查找算法,实现对大数值数组的索引优化。离散化过程中,先对数组进行排序、去重,然后通过二分查找获取每个元素在新数组中的位置,并更新原数组。此外,还展示了自定义的二分查找函数的实现。
摘要由CSDN通过智能技术生成

目录

数组离散化应用场景:数组的值过大,不能用作数组的索引或者可用作数组索引但是会导致空间复杂度过大,而要解决的问题中只需要考虑元素之间的相对大小,不必考虑数组之间的绝对大小,比如求逆序对问题。数组离散化使用C++可很简单的实现,STL中有sort和unique,还有二分查找lower_bound。Java也有这些函数。本文使用jdk8的新特性—stream来实现数组离散化。

二分查找简介

二分查找应用场景:容器(数组或者集合)中的元素有序,且要根据value查找index。二分查找使用的是分治思想,不断将查找范围一分为二,直到找到给定的value或者找不到value返回。Java中的工具类Arrays和Collections中都有binarySearch函数,前者用于数组中的二分,后者用于集合的二分。在这里我是自己实现的二分查找,采用尾递归的形式进行二分查找,当然也可以用循环。代码如下:

public static int binarySearch(Integer[]arr,int s,int e,int val){
    if(s>e)
        return -1;
    int ans=-1;
    int mid=(s+e)/2;
    if(arr[mid]==val)
        return mid;
    if(arr[mid]<val)
        return binarySearch(arr,mid+1,e,val);
    return binarySearch(arr,s,mid-1,val);
    }

stream简介

jdk8的新特性stream,是一个非常强大好用的工具。像Array,Collection,Map这些都是Java的数据结构,是早就有了的,对应的Arrays,Collections中为这些数据结构提供相应的算法,但是并不是很快捷方便。而stream就是为这些数据结构提供了更强大的函数式编程的算法。要对容器排序,直接使用.sorted(),参数可以传一个lambda表达式,要对容器去重,直接.distinct(),最后要转换成数组的话,.toArray(Integer[]::new),注意里面的参数,是lambda函数的构造器引用,也是jdk8的新特性,还有成员方法引用,类静态方法引用等,再次不做详细扩展。

数组离散化的实现

思路:通过stream对传进来的数组排序、去重并通过终止操作toArray()转换成Integer[]数组,再遍历原数组中的每一个元素,查找该元素值在得到的Integer[]数组中的index,然后修改原数组中该指为index+1(这个随便,用index也没毛病,但是index+1就保证了从1开始,比如原数组:6 5 2 1 9,离散化后:4 3 2 1 5,和相对大小顺序是一样的),然后返回修改后的数组即可。代码如下:

public static int[] discrete(int[]copy){
        Integer[] integers = Arrays.stream(copy).boxed().parallel().sorted().distinct().toArray(Integer[]::new);

        for(int i=0;i<copy.length;++i){
            int index=binarySearch(integers,0,integers.length,copy[i]);
            copy[i]=index+1;
        }
        return copy;
    }

完整代码

public class ArrayDiscrete {

public static int binarySearch(Integer[]arr,int s,int e,int val){
    if(s>e)
        return -1;
    int ans=-1;
    int mid=(s+e)/2;
    if(arr[mid]==val)
        return mid;
    if(arr[mid]<val)
        return binarySearch(arr,mid+1,e,val);
    return binarySearch(arr,s,mid-1,val);
    }

    public static int[] discrete(int[]copy){
        Integer[] integers = Arrays.stream(copy).boxed().parallel().sorted().distinct().toArray(Integer[]::new);

        for(int i=0;i<copy.length;++i){
            int index=binarySearch(integers,0,integers.length,copy[i]);
            copy[i]=index+1;
        }
        return copy;
    }
    public static void main(String[] args) {
        int[]arr=new int[]{6,5,3,6,9,1};
        int[] ans=discrete(arr);
        System.out.println(Arrays.toString(ans));

    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值