生活随笔
收集整理的這篇文章主要介紹了
二分法:两个有序数组长度为N,找到第N、N+1大的数
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目
兩個有序數(shù)組長度為N,找到第N、N+1大的數(shù)
思路1:雙指針,O(N)復(fù)雜度
簡述思路:
如果當(dāng)前A指針指向的數(shù)組A的內(nèi)容小于B指針指向的數(shù)組B的內(nèi)容,那么A指針往右移動,然后nums(當(dāng)前已經(jīng)遍歷過的數(shù)字個數(shù))也加一。
如果此時已經(jīng)遍歷過的數(shù)字個數(shù)等于N那么九江移動之前的A指針指向的A數(shù)組的內(nèi)容送入result。
其他情況,以相反的邏輯進(jìn)行。
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
;}}}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:迭代法二分
簡述思路:
先初始化ab數(shù)組的start,end,mid;
然后比較各自mid指向的值的大小。
如果A[a_mid] > B[b_mid],說明,第N大的值在A數(shù)組a_mid的左邊,在B數(shù)組b_mid的右邊,所以對a_end以及b_start做出更新:
長度為奇數(shù)的時候,正好
a_end = a_mid;
b_start = b_mid;
當(dāng)然還要考慮到長度為偶數(shù)的情況:
a_end = a_mid;
b_start = b_mid + 1;
這里只是對start進(jìn)行修改,對于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] ,并且,長度為偶數(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] ,并且,長度為偶數(shù),所以
a_start = a_mid =1;
b_end = b_mid =2;
此時達(dá)成a_start == a_end || b_start == b_end條件,所以可以判斷兩個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;while (a_start
!= a_end
|| b_start
!= b_end
){a_mid
= (a_start
+ a_end
) / 2;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
;}else if (A
[a_mid
] > B
[b_mid
]){if ((a_start
+ a_end
) % 2 == 0){a_end
= a_mid
;b_start
= b_mid
;}else{a_end
= a_mid
;b_start
= b_mid
+ 1;}}else{if ((a_start
+ a_end
) % 2 == 0){a_start
= a_mid
;b_end
= b_mid
;}else{a_start
= a_mid
+ 1;b_end
= b_mid
;}}}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> 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ù)的一開始寫終止條件,參考迭代法。
終止條件后面,寫根據(jù)中間值的大小,對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
){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
]){if ((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
);}}else{if ((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 };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大的数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。