![](/img/trans.png)
[英]Lower Bound Binary Search c++ (if checked[mid], get the next biggest value that is not bigger than the used value)
[英]Get mid value in C++
考慮三個值x, y, z
。
得到中間值(不是平均值,而是既不是min
也不是max
)的公式是什么?
const double min = std::min(x, std::min(y, z));
const double mid = /* what formula here ? */
const double max = std::max(x, std::max(y, z));
以對稱方式一次找到所有三個:
min = x; med = y; max = z;
if (min > med) std::swap(min, med);
if (med > max) std::swap(med, max);
if (min > med) std::swap(min, med);
這似乎在作弊,但是: x + y + z - min - max
該鏈接的答案在評論中共享:
const double mid = std::max(std::min(x,y),std::min(std::max(x,y),z));
編輯 -正如艾倫所指出的,我錯過了一個案子。 我現在給出了更直觀的證明。
直接證明 :關於x和y不失一般性。
從最里面的表達式開始, min(max(x,y),z)
...
max(min(x,y),z)
。 通過這一點,我們能夠確定min(x,y)與z之間的關系。 max(min(x,y),z)
返回該中位數。 max(min(x,y),x)
。 由於max(x,y)評估為x,因此min(x,y)評估為y。 得到關系z> x> y 。 我們返回x和y的最大值(隨着表達式變為max(y,x)
),它是x也是中位數。 (請注意,y的證明是對稱的) 證明結束
舊證明-注意它不完整 (直接):
不失一般性:假設x> y> z
x和y的最小值為y。 (x和y的最大值)和z的最小值是z。
y和z的最大值為y,即中位數。
假設x = y> z
x和y的最小值表示為x。 最小值(x和y的最大值是x)和z是z。
以上兩個的最大值是x,這是中位數。
假設x> y = z
x和y的最小值為y。 最小值(x和y的最大值是x)和z是z。
上述兩個的最大值是y,即中位數。
最后,假設x = y = z
這三個數字中的任何一個都是中位數。並且使用的公式將返回某個數字。
它比Alan的技巧丑陋一些,但它不會導致溢出或數值錯誤,等等:
int x, y, z, median;
...
if (x <= y && y <= z || y >= z && y <= x) median = y;
else if (y <= x && x <= z || x >= z && x <= y) median = x;
else median = z;
算法很簡單:
檢查x是否在y和z之間,如果是,則是。
檢查y是否在x和z之間,如果是,則是。
由於它既不是x也不是y,因此必須為z。
================================================== ===
如果您具有三個以上的元素,則還可以更靈活地進行排序。
//或xor實現,沒關系...
void myswap(int * a,int * b){int temp = * b; * b = * a; * a =溫度; }
int x, y, z;
// Initialize them
int min = x;
int med = y;
int max = z;
// you could also use std::swap here if it does not have to be C compatible
// In that case, you could just pass the variables without the address operator.
if (min > med) myswap(&min, &med);
if (med > max) myswap(&med, &max);
if (min > med) myswap(&min, &med);
艾倫“騙子”的一種變體,可以防止溢出:
#include <iostream>
#include <algorithm>
using namespace std;
int main(int argc, char *argv[]) {
double a = 1e308;
double b = 6e306;
double c = 7.5e18;
double mn = min(a,min(b,c));
double mx = max(a,max(b,c));
double avg = mn + (mx-mn)*0.5;
double mid = a - avg + b - avg + c;
cout << mid << endl;
}
輸出:
6e+306
它利用二進制搜索中經常使用的avg公式來防止溢出:
兩個值的平均值可以計算為low + (high-low)/2
但是,它僅適用於正值。 可能的回退包括Alan的答案,或者對於平均值計算僅是(x+y)/2
。
請注意,雙精度會在這里起作用,並且可能導致mid
計算出現問題。 它對於正整數確實非常有效:)
最好的方法是使用通用中值函數模板。 無需復制,交換或數學運算。
template <typename T>
const T& median(const T& a, const T& b, const T& c)
{
if (a < b)
if (b < c)
return b;
else if (a < c)
return c;
else
return a;
else if (a < c)
return a;
else if (b < c)
return c;
else
return b;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.