ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2. 离散化

2022-02-28 16:59:04  阅读:159  来源: 互联网

标签:util set int 离散 import public


离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。

概述

离散化本质上可以看成是一种哈希,是程序设计中一个常用的技巧,它可以有效的降低时间复杂度。其基本思想就是在众多可能的情况中,只考虑需要用的值。离散化可以改进一个低效的算法,甚至实现根本不可能实现的算法。

通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。例如:
原数据:1,999,100000,15;处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};

实现

C++ 离散化有现成的 STL 算法:

// 思路:先排序,再删除重复元素,最后就是索引元素离散化后对应的值
// a[i] 为初始数组,下标范围为 [1, n]
// len 为离散化后数组的有效长度
std::sort(a + 1, a + 1 + n);

len = std::unique(a + 1, a + n + 1) - a - 1;
// 离散化整个数组的同时求出离散化后本质不同数的个数。

// 在完成上述离散化之后可以使用 std::lower_bound 函数查找离散化之后的排名(即新编号):
std::lower_bound(a + 1, a + len + 1, x) - a;  // 查询 x 离散化后对应的编号

Java 自实现版本

import java.util.Arrays;
import java.util.SortedSet;
import java.util.TreeSet;

public class Discretization {
    public static int lowerBound(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]);
        }

        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]=lowerBound(b,array[i])+1; //利用lowerBound找到该数值的排位(rank)
            //排名代表大小 越前越小 越后越大
        }
        //10000000,2,2,123123213离散化成2,1,1,3
        return array;
    }
    public static void main(String[] args) {
        int[] a={10000000,2,2,123123213};
        System.out.println(Arrays.toString(solve(a)));
    }
}

实战

Leetcode 剑指 Offer 51. 数组中的逆序对

题解

使用了树状数组+离散化

import java.util.HashMap;
import java.util.SortedSet;
import java.util.TreeSet;

class Solution {
    int[] t = new int[50002];

    public int lowBit(int x) {
        return x & -x;
    }

    public int query(int i) {
        int ans = 0;
        for (--i; i > 0; i -= lowBit(i) ) {
            ans += t[i];
        }
        return ans;
    }

    public void update(int i, int x) {
        for (; i < t.length; i += lowBit(i)) {
            t[i] += x;
        }
    }

    public int reversePairs(int[] nums) {
        SortedSet<Integer> set = new TreeSet<>();
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            set.add(nums[i]);
        }

        int i = set.size() + 1;
        for(int x : set) {
            map.put(x, i);
            i--;
        }

        int ans = 0;
        for (i = 0; i < nums.length; i++) {
            int hi = map.get(nums[i]);
            ans += query(hi);
            update(hi, 1);
        }
        return ans;
    }
}

标签:util,set,int,离散,import,public
来源: https://blog.csdn.net/qq_35129075/article/details/123184133

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有