• 关于离散化的小认知


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

    有些数据本身很大, 自身无法作为数组的下标保存对应的属性。

    如果这时只是需要这堆数据的相对属性, 那么可以对其进行离散化处理!

    离散化:当数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。

     1 0 5 4 与 5 2 1 4 3 的逆序对个数相同。
    设有4个数:
    1234567、123456789、12345678、123456
    排序:123456<1234567<12345678<123456789
               =>     1     <        2       <        3       <        4
    那么这4个数可以表示成:2、4、3、1.

    32434234,32434234,43324556,8384733,98998988

    去重后给予其对应的索引:0,0,1,2,3分别对应每个数,就可以简化很多操作,减少了很多不必要的资源开销。

    除了对于较大整数需要使用离散化之外,对于一些需要使用整型数据结构,但给出的数据却是小数的也可以使用离散化,将其索引为整数就可以了。

    那么可以总结出离散化的步骤:

    1、排序

    2、去重

    3、索引

    为了简化代码,我们采用STL算法离散化:

    int a[n], b[n], sub[n]; //a[n]是即将被离散化的数组,b[n]是a[n]的副本,sub用于排序去重后提供离散化后的值
    sort(sub, sub + n);
    int size = unique(sub, sub + n) - sub;
    for(int i = 0; i < n; i++)
        a[i] = lower_bound(sub, sub + size, a[i]) - sub; //即a[i]为b[i]离散化后对应的值

    对于第3步,若离散化后序列为0, 1, 2, ..., size - 1则用lower_bound,从1, 2, 3, ..., size则用upper_bound,其中lower_bound返回第1个不小于b[i]的值的指针,而upper_bound返回第1个大于b[i]的值的指针,当然也可以用lower_bound然后再加1得到与upper_bound相同结果,两者都是针对以排好序列。使用STL离散化大大减少了代码量且结构相当清晰。

    离散化后查询的问题(采用的如上代码的离散方式):

    1、通过离散后的值查询离散前的值:

      若离散后的值为x,那么对应的离散前的值为sub[x];

    2、通过离散前的下标查询离散后的值:

      若离散前的下标为i,那么对应的离散后的值为a[i];

    3、通过离散前的值查询离散后的值:

      如果没有相应的保存的话,首先要确定y在sub[]中的位置,或者在b[]中的位置,前者可以使用pos = lower_bound(sub, sub+size, y) - sub。那么pos即为下标,通过第二步再查询就好了。

    下面附上关于unique函数的简单应用。

    • 现在总结一下unique,unique的作用是“去掉”容器中相邻元素的重复元素(不一定要求数组有序),它会把重复的元素添加到容器末尾(所以数组大小并没有改变),而返回值是去重之后的尾地址,下面举个例子。
    • 由于返回的是容器末尾,所以如果想得到去重后的size,需要减去初始地址,lower_bound是得到地址,稍微不同。
    •   sz = unique(b + 1,b + n + 1)-(b + 1);
        sz = unique(a,a + n) - a;
    • 如果要删去重复元素,可以把尾巴删去即可(或者直接定义新的长度!)。
    • #include <iostream>
      #include <cassert>
      #include <algorithm>
      #include <vector>
      #include <string>
      #include <iterator>
      using namespace std;
      int main()
      {
          const int N=11;
          int array1[N]={1,2,0,3,3,0,7,7,7,0,8};
          vector<int> vector1;
          for (int i=0;i<N;++i)
              vector1.push_back(array1[i]);
      
          vector<int>::iterator new_end;
          new_end=unique(vector1.begin(),vector1.end());    //"删除"相邻的重复元素
          assert(vector1.size()==N);
      
          vector1.erase(new_end,vector1.end());  //删除(真正的删除)重复的元素
          copy(vector1.begin(),vector1.end(),ostream_iterator<int>(cout," "));
          cout<<endl;
      
          return 0;
      }

       学习出粗

  • 相关阅读:
    加速 gradle 打包速度 !!
    坑爹的希腊字母 ο
    09 你这导师太假了,不如换个学术大佬 !
    导师不敢和你说的水论文隐藏技巧,只教你水论文
    12 水论文如何吹一个好故事
    07 导师不敢和你说的水论文隐藏技巧,毕业论文,小论文和综述的区别,三者怎么进行换汤不换药转换
    04 导师不敢和你说的水论文隐藏技巧,论文模型需不需要继承
    从Python到水一篇AI论文(核心 or Sci三区+)(目录)
    05 导师不敢和你说的水论文隐藏技巧,没有继承且无法复现论文模型怎么办?如何做一个好的学术裁缝
    06 导师不敢和你说的水论文隐藏技巧,顶刊、顶会、水刊的论文读哪个,如何做一个称职的学术裁缝.md
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/9052030.html
Copyright © 2020-2023  润新知