日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

二分法:两个有序数组长度为N,找到第N、N+1大的数

發(fā)布時(shí)間:2023/12/1 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二分法:两个有序数组长度为N,找到第N、N+1大的数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目

兩個(gè)有序數(shù)組長(zhǎng)度為N,找到第N、N+1大的數(shù)

思路1:雙指針,O(N)復(fù)雜度

簡(jiǎn)述思路:
如果當(dāng)前A指針指向的數(shù)組A的內(nèi)容小于B指針指向的數(shù)組B的內(nèi)容,那么A指針往右移動(dòng),然后nums(當(dāng)前已經(jīng)遍歷過(guò)的數(shù)字個(gè)數(shù))也加一。
如果此時(shí)已經(jīng)遍歷過(guò)的數(shù)字個(gè)數(shù)等于N那么九江移動(dòng)之前的A指針指向的A數(shù)組的內(nèi)容送入result。
其他情況,以相反的邏輯進(jìn)行。

//雙指針?lè)ㄇ蠼?/span> vector<int> GetMid_On(vector<int>& A, vector<int>& B, int N) {int A_index = 0;int B_index = 0;int nums = 0;vector<int> result;while (A_index < N && B_index < N){if (A[A_index] < B[B_index]){A_index++;nums++;if (nums == N){result.push_back(A[A_index - 1]);}if (nums == N + 1){result.push_back(A[A_index - 1]);return result;}}else {B_index++;nums++;if (nums == N){result.push_back(B[B_index - 1]);}if (nums == N + 1){result.push_back(B[B_index - 1]);return result;}}//如果兩個(gè)元素相同}return result; }int main() {vector<int> A = { 2,4,5,6,9 };vector<int> B = { 1,3,7,8,10 };vector<int> result = GetMid_On(A, B, 5);cout << result[0] << endl;cout << result[1] << endl;cout << "結(jié)束" << endl;return 0; }

思路2:迭代法二分

簡(jiǎn)述思路:
先初始化ab數(shù)組的start,end,mid;
然后比較各自mid指向的值的大小。
如果A[a_mid] > B[b_mid],說(shuō)明,第N大的值在A數(shù)組a_mid的左邊,在B數(shù)組b_mid的右邊,所以對(duì)a_end以及b_start做出更新:
長(zhǎng)度為奇數(shù)的時(shí)候,正好
a_end = a_mid;
b_start = b_mid;
當(dāng)然還要考慮到長(zhǎng)度為偶數(shù)的情況:
a_end = a_mid;
b_start = b_mid + 1;
這里只是對(duì)start進(jìn)行修改,對(duì)于end值不需要修改??梢耘e例:
A = {2,4,6,8};
B= {1,3,5,7};
a_start = 0,a_end = 3
b_start = 0,b_end = 3
a_mid = b_mid = 3/2 =1;
A[a_mid] > B[b_mid] ,并且,長(zhǎng)度為偶數(shù),所以
a_end = a_mid =1;
b_start = b_mid +1 =2;
所以A被分割為:{2,4};
B被分割為:{5,7};
a_start = 0,a_end = 1
b_start = 2,b_end = 3
a_mid = 1/2 =0;
b_mid = (2+3)/2= 2;
A[a_mid] < B[b_mid] ,并且,長(zhǎng)度為偶數(shù),所以
a_start = a_mid =1;
b_end = b_mid =2;
此時(shí)達(dá)成a_start == a_end || b_start == b_end條件,所以可以判斷兩個(gè)start的值的大小,取較小值可得到第N大的數(shù):

//迭代二分法去解 vector<int> GetMid(vector<int>& A, vector<int>& B, int N) {vector<int> result;int a_start = 0, a_end = N - 1;int b_start = 0, b_end = N - 1;//初始化中間位置int a_mid = (a_start + a_end) / 2;int b_mid = (b_start + b_end) / 2;//循環(huán)結(jié)束條件:當(dāng)數(shù)組起始點(diǎn)與結(jié)束點(diǎn)重合的時(shí)候,說(shuō)明存在第N大的數(shù)while (a_start != a_end || b_start != b_end){//更新中間坐標(biāo)a_mid = (a_start + a_end) / 2;b_mid = (b_start + b_end) / 2;//如果此時(shí)的A中位數(shù)與B的中位數(shù)相同,說(shuō)明兩個(gè)都是第N大的數(shù)if (A[a_mid] == B[b_mid]){result.push_back(A[a_mid]);result.push_back(A[a_mid] > B[b_mid] ? B[b_mid]: A[a_mid]);return result;}//如果A的中位數(shù)>B的中位數(shù),說(shuō)明此時(shí)第N大的數(shù)在A的左邊,B的右邊,所以需要更新a_end以及b_startelse if (A[a_mid] > B[b_mid]){//如果當(dāng)前a_start-a_end之間的長(zhǎng)度為偶數(shù),那么中間值就是midif ((a_start + a_end) % 2 == 0){a_end = a_mid;b_start = b_mid;}else{a_end = a_mid;b_start = b_mid + 1;}}//如果A的中位數(shù)<B的中位數(shù),說(shuō)明此時(shí)第N大的數(shù)在A的右邊,B的左邊,所以需要更新a_start以及b_endelse{//如果當(dāng)前a_start-a_end之間的長(zhǎng)度為奇數(shù),那么中間值就是midif ((a_start + a_end) % 2 == 0){a_start = a_mid;b_end = b_mid;}//如果當(dāng)前a_start-a_end之間的長(zhǎng)度為偶數(shù),那么中間值就是mid+1else{a_start = a_mid + 1;b_end = b_mid;}}}//判斷兩個(gè)start的值的大小if (A[a_start] > B[b_start]){result.push_back(B[b_start]);if (b_start + 1 < N){if (A[a_start] > B[b_start + 1])result.push_back(B[b_start + 1]);elseresult.push_back(A[a_start]);}elseresult.push_back(A[a_start]);}else{result.push_back(A[a_start]);if (a_start + 1 < N){if (A[a_start + 1] <= B[b_start])result.push_back(A[a_start + 1]);elseresult.push_back(B[b_start]);}elseresult.push_back(B[b_start]);}return result; }int main() {vector<int> A = { 2,4,5,6,9 };vector<int> B = { 2,4,5,6,9 };//vector<int> B = { 1,3,7,8,10 };vector<int> result = GetMid(A, B, 5);for(int i = 0;i < result.size();i++)cout << result[i] << endl;cout << "結(jié)束" << endl;return 0; }

思路3:遞歸法二分

寫完迭代法之后,遞歸將a_start,a_end,b_start,b_end,作為遞歸函數(shù)的參數(shù)放入。遞歸函數(shù)的一開(kāi)始寫終止條件,參考迭代法。
終止條件后面,寫根據(jù)中間值的大小,對(duì)a_start,a_end,b_start,b_end進(jìn)行不同賦值,達(dá)到分割數(shù)組的目的。

//遞歸二分法求解 vector<int> GetMid(vector<int>& A, vector<int>& B, int a_start,int a_end,int b_start,int b_end,int N) {vector<int> result;//初始化中間位置int a_mid = (a_start + a_end) / 2;int b_mid = (b_start + b_end) / 2;//如果有答案了if (A[a_mid] == B[b_mid]){result.push_back(A[a_mid]);result.push_back(A[a_mid] > B[b_mid] ? B[b_mid] : A[a_mid]);return result;}if (a_start == a_end || b_start == b_end){//判斷兩個(gè)start的值的大小if (A[a_start] > B[b_start]){result.push_back(B[b_start]);if (b_start + 1 < N){if (A[a_start] > B[b_start + 1])result.push_back(B[b_start + 1]);elseresult.push_back(A[a_start]);}elseresult.push_back(A[a_start]);}else{result.push_back(A[a_start]);if (a_start + 1 < N){if (A[a_start + 1] <= B[b_start])result.push_back(A[a_start + 1]);elseresult.push_back(B[b_start]);}elseresult.push_back(B[b_start]);}return result;}//遞歸更新邊界值if (A[a_mid] > B[b_mid]){//如果當(dāng)前a_start-a_end之間的長(zhǎng)度為偶數(shù),那么中間值就是midif ((a_start + a_end) % 2 == 0){return GetMid(A, B, a_start, a_mid, b_mid, b_end, N);}else{return GetMid(A, B, a_start, a_mid, b_mid + 1, b_end, N);}}//如果A的中位數(shù)<B的中位數(shù),說(shuō)明此時(shí)第N大的數(shù)在A的右邊,B的左邊,所以需要更新a_start以及b_endelse{//如果當(dāng)前a_start-a_end之間的長(zhǎng)度為偶數(shù),那么中間值就是midif ((a_start + a_end) % 2 == 0){return GetMid(A, B, a_mid, a_end, b_start, b_mid, N);}else{return GetMid(A, B, a_mid + 1, a_end, b_start, b_mid, N);}} }int main() {vector<int> A = { 2,4,5,6,9 };//vector<int> B = { 2,4,5,6,9 };int N = A.size();vector<int> B = { 1,3,7,8,10 };vector<int> result = GetMid(A, B, 0, N-1,0,N-1,N);for(int i = 0;i < result.size();i++)cout << result[i] << endl;cout << "結(jié)束" << endl;return 0; }

總結(jié)

以上是生活随笔為你收集整理的二分法:两个有序数组长度为N,找到第N、N+1大的数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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