日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

离散化+unique()+二分查找

發(fā)布時(shí)間:2025/4/14 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 离散化+unique()+二分查找 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

離散化

引自百度百科
離散化,把無限空間中有限的個(gè)體映射到有限的空間中去,以此提高算法的時(shí)空效率。
通俗的說,離散化是在不改變數(shù)據(jù)相對(duì)大小的條件下,對(duì)數(shù)據(jù)進(jìn)行相應(yīng)的縮小。例如:
原數(shù)據(jù):1,999,100000,15;處理后:1,3,4,2;
原數(shù)據(jù):{100,200},{20,50000},{1,400};
處理后:{3,4},{2,6},{1,5};

離散化是程序設(shè)計(jì)中一個(gè)常用的技巧,它可以有效的降低時(shí)間復(fù)雜度。其基本思想就是在眾多可能的情況中,只考慮需要用的值。離散化可以改進(jìn)一個(gè)低效的算法,甚至實(shí)現(xiàn)根本不可能實(shí)現(xiàn)的算法。要掌握這個(gè)思想,必須從大量的題目中理解此方法的特點(diǎn)。例如,在建造線段樹空間不夠的情況下,可以考慮離散化。

數(shù)據(jù)的離散化

有些數(shù)據(jù)本身很大, 自身無法作為數(shù)組的下標(biāo)保存對(duì)應(yīng)的屬性。如果這時(shí)只是需要這堆數(shù)據(jù)的相對(duì)屬性, 那么可以對(duì)其進(jìn)行離散化處理。當(dāng)數(shù)據(jù)只與它們之間的相對(duì)大小有關(guān),而與具體是多少無關(guān)時(shí),可以進(jìn)行離散化。
例 1:
91054 與 52143的逆序?qū)€(gè)數(shù)相同。
例 2:
設(shè)有4個(gè)數(shù): 1234567、123456789、12345678、123456
排序:123456<1234567<12345678<123456789
=>1<2<3<4
那么這4個(gè)數(shù)可以表示成:2、4、3、1
例 3:
比如給你n個(gè)數(shù):98998988,32434234,433234556,32434234,8384733,……
讓你統(tǒng)計(jì)其中每個(gè)數(shù)出現(xiàn)的次數(shù),傳統(tǒng)的做法有好幾種,比如一遍一遍的掃過去,比對(duì)疊加,這樣算法的效率是O(n2),效率低下;
再比如先排序,再統(tǒng)計(jì)連續(xù)的相同的個(gè)數(shù),這里的效率已經(jīng)有所提高了,不過假如上面的數(shù)據(jù)是一道線段樹的題目給出的數(shù)據(jù),那么建樹需要的空間開銷實(shí)在是太大了。
再改進(jìn)一下,采用哈希的方法,開一個(gè)大于其中最大數(shù)的數(shù)組并初始化為零,O(n)掃一下,在該數(shù)字對(duì)應(yīng)的下標(biāo)的元素上+1,如果對(duì)于比較小的數(shù)字還好說,但是對(duì)于上面出現(xiàn)的數(shù)字直接采用哈希對(duì)空間的開銷是十分大的也是沒有必要的,所以這里用到了數(shù)據(jù)的離散化。
首先將數(shù)字排序:32434234,32434234,43324556,8384733,98998988
去重后給予其對(duì)應(yīng)的索引: 0,0,1,2,3 (一一映射)
分別對(duì)應(yīng)每個(gè)數(shù),就可以簡(jiǎn)化很多操作,減少了很多不必要的資源開銷。
除了對(duì)于較大整數(shù)需要使用離散化之外,對(duì)于一些需要使用整型數(shù)據(jù)結(jié)構(gòu),但給出的數(shù)據(jù)卻是小數(shù)的也可以使用離散化,將其索引為整數(shù)就可以了。

那么可以總結(jié)出離散化的步驟:

1、排序

2、去重

3、索引
為了簡(jiǎn)化代碼,我們采用STL算法離散化:

/* 用離散化之前先用 sort()排序,再用 unique() 進(jìn)行去重 用 lower_bound() 或者 upper_bound() 進(jìn)行二分查找位置 */ int a[n], b[n], sub[n]; // a[n]是即將被離散化的數(shù)組,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]離散化后對(duì)應(yīng)的值

1、unique()函數(shù)————返回值是去重之后的長(zhǎng)度

unique() 的作用是“去掉”容器中相鄰元素的重復(fù)元素(不一定要求數(shù)組有序),即去重
它會(huì)把重復(fù)的元素添加到容器末尾(所以數(shù)組大小并沒有改變),而返回值是去重之后的尾地址
如果要?jiǎng)h去重復(fù)元素,可以把尾巴刪去即可(或者直接定義新的長(zhǎng)度!)
例如:

sz=unique(b+1,b+n+1)-(b+1);//減去的(b+1) 及 a 是起始地址 sz=unique(a,a+n)-a;

2、二分查找——lower_bound()、upper_bonud()

/* upper_bound(i) 返回的是鍵值為i的元素可以插入的最后一個(gè)位置(上界) lowe_bound(i) 返回的是鍵值為i的元素可以插入的位置的第一個(gè)位置(下界)。 */

怎么理解呢,舉例:
在升序的set里面
set里沒有元素i的時(shí)候,兩個(gè)元素的返回值是一樣的。
1 2 4 5 這個(gè)序列,upp(3)和low(3)都返回位置2(下標(biāo))

如果只有一個(gè)元素i,low返回那個(gè)元素的位置,而upp返回那個(gè)元素的位置的后一個(gè)位置。
1 2 4 5 這個(gè)序列upp(2)返回下標(biāo)2而low(2)返回下標(biāo)1

多個(gè)元素i,low返回那個(gè)元素的位置,upp返回那多個(gè)元素中的最后一個(gè)的后一個(gè)位置。
1 2 2 4 5 這個(gè)序列 upp(2)返回下標(biāo)3的位置,low(2)返回下標(biāo)1的位置。

!!!!!!!!!!!!!
特別注意:舉例在一個(gè)升序的容器里,如果所有元素都大于i則,upp和low都返回begin。都小于i則返回end(越界了)。

最后再來一句,看是否好理解一些。

terator lower_bound( const key_type &key ): 返回一個(gè)迭代器,指向鍵值>= key的第一個(gè)元素。
iterator upper_bound( const key_type &key ):返回一個(gè)迭代器,指向鍵值<=key的最后一個(gè)元素的后一個(gè)元素。
★降序排列的容器:
iterator lower_bound( const key_type &key ): 返回一個(gè)迭代器,指向鍵值<= key的第一個(gè)元素。
iterator upper_bound( const key_type &key ):返回一個(gè)迭代器,指向鍵值>=key的最后一個(gè)元素的后一個(gè)元素。
例如:

bool cmp(int a,int b) {return a<b; } int main() {int a[10]={2,7,1,4,4,6};sort(a,a+6,cmp); // 去重之前先排序int m=unique(a,a+6)-a; // 去重cout<<m<<endl; // 輸出去重之后的長(zhǎng)度for(int i=0;i<m;i++)cout<<a[i]<<' '; // 輸出去重之后的數(shù)cout<<endl;int tem=upper_bound(a,a+6,4)-a;//按從小到大 4 最多能插入數(shù)組 a 的哪個(gè)位置int p=lower_bound(a,a+6,4)-a;//按從小到大,4最少能插入數(shù)組 a 的哪個(gè)位置cout<<tem<<endl;cout<<p<<endl; }輸出 5 1 2 4 6 7 3 2

轉(zhuǎn)載于:https://www.cnblogs.com/zcy19990813/p/9702745.html

總結(jié)

以上是生活随笔為你收集整理的离散化+unique()+二分查找的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。