Java 找到三元组中间值的最快方法?

Java 找到三元组中间值的最快方法?,java,algorithm,conditional,logic,median,Java,Algorithm,Conditional,Logic,Median,给定的是一个由三个数值组成的数组,我想知道这三个数值的中间值 问题是,找到三者中间位置的最快方法是什么 我的方法是这种模式——因为有三个数字,所以有六种排列: if (array[randomIndexA] >= array[randomIndexB] && array[randomIndexB] >= array[randomIndexC]) 如果有人能帮我找到一种更优雅、更快捷的方法,那就太好了。以下是仅使用条件表达的方法: int a, b, c =

给定的是一个由三个数值组成的数组,我想知道这三个数值的中间值

问题是,找到三者中间位置的最快方法是什么

我的方法是这种模式——因为有三个数字,所以有六种排列:

if (array[randomIndexA] >= array[randomIndexB] &&
    array[randomIndexB] >= array[randomIndexC])

如果有人能帮我找到一种更优雅、更快捷的方法,那就太好了。

以下是仅使用条件表达的方法:

int a, b, c = ...
int middle = (a <= b) 
    ? ((b <= c) ? b : ((a < c) ? c : a)) 
    : ((a <= c) ? a : ((b < c) ? c : b));
inta,b,c=。。。

int middle=(a在ary中使用idxA到idxC

int ab = ary[idxA] < ary[idxB] ? idxA : idxB;
int bc = ary[idxB] < ary[idxC] ? idxB : idxC;
int ac = ary[idxA] < ary[idxC] ? idxA : idxC;

int idxMid = ab == bc ? ac : ab == ac ? bc : ab;
intab=ary[idxA]
indexMiddle指向中间值


说明:从3个最小值中,2是总体最小值,另一个值必须是中间值。因为我们检查了相等性,所以可以比较最后一行中的索引,而不必比较数组值。

或一个用于在包含中间值的数组中查找索引的一行:

 int middleIndex = (a[0]<a[1]) ? ((a[0]<a[2) ? a[2] : a[0]) : ((a[1]<a[2) ? a[2] : a[1]);

int middleIndex=(a[0]如果您正在寻找最有效的解决方案,我可以想象它是这样的:

if (array[randomIndexA] > array[randomIndexB]) {
  if (array[randomIndexB] > array[randomIndexC]) {
    return "b is the middle value";
  } else if (array[randomIndexA] > array[randomIndexC]) {
    return "c is the middle value";
  } else {
    return "a is the middle value";
  }
} else {
  if (array[randomIndexA] > array[randomIndexC]) {
    return "a is the middle value";
  } else if (array[randomIndexB] > array[randomIndexC]) {
    return "c is the middle value";
  } else {
    return "b is the middle value";
  }
}
max(a,b)=(a+b+|a-b|)/2
min(a,b)=(a+b-|a-b|)/2
private static long median(Integer i1, Integer i2, Integer i3) {

    List<Integer> list = Arrays.asList(
            i1 == null ? 0 : i1,
            i2 == null ? 0 : i2,
            i3 == null ? 0 : i3);

    Collections.sort(list);
    return list.get(1);
}

这种方法需要至少两次,最多三次比较。它故意忽略两个值相等的可能性(就像你的问题一样):如果这很重要,可以扩展方法来检查这一点。

如果必须从X个值中找到一个满足某些标准,则必须至少将该值与X-1其他值中的每个值进行比较。对于三个值,这意味着至少两次比较。因为这是“查找非最小值和非最大值”你只需要做两次比较就可以成功

然后,您应该集中精力编写代码,以便能够非常清楚地看到发生了什么,并保持简单。这里的意思是嵌套if。这将允许JVM在运行时尽可能地优化此比较


请参阅Tim()提供的解决方案看一个例子。许多代码行不一定比嵌套问号colon的代码大。

你最好用最简单的方式来写。正如你所说,只有六种可能。没有合理的方法会更快或更慢,所以只需要简单易读。


为了简洁起见,我会使用min()和max(),但我认为三个嵌套的if/thens也一样好。

这最多可以通过两个比较来完成

int median(int a, int b, int c) {
    if ( (a - b) * (c - a) >= 0 ) // a >= b and a <= c OR a <= b and a >= c
        return a;
    else if ( (b - a) * (c - b) >= 0 ) // b >= a and b <= c OR b <= a and b >= c
        return b;
    else
        return c;
}
整数中值(整数a、整数b、整数c){

如果((a-b)*(c-a)>=0)//a>=b和a=0)//b>=a和b如果硬件能够在没有分支的情况下回答最小和最大查询,那么就有可能在没有分支的情况下回答查询(今天的大多数CPU都可以这样做)

运算符^表示按位异或

Input: triple (a,b,c)
1. mx=max(max(a,b),c)
2. mn=min(min(a,b),c)
3. md=a^b^c^mx^mn
4. return md
这是正确的,因为:

  • 异或是交换的和结合的
  • 相等位上的异或产生零
  • 带零的异或不改变位
应为int/float选择适当的min/max函数。 如果只存在正浮点,则可以直接在浮点表示上使用整数min/max(这可能是可取的,因为整数运算通常更快)

在硬件不支持最小/最大的不太可能的情况下,可以执行以下操作:

if (array[randomIndexA] > array[randomIndexB]) {
  if (array[randomIndexB] > array[randomIndexC]) {
    return "b is the middle value";
  } else if (array[randomIndexA] > array[randomIndexC]) {
    return "c is the middle value";
  } else {
    return "a is the middle value";
  }
} else {
  if (array[randomIndexA] > array[randomIndexC]) {
    return "a is the middle value";
  } else if (array[randomIndexB] > array[randomIndexC]) {
    return "c is the middle value";
  } else {
    return "b is the middle value";
  }
}
max(a,b)=(a+b+|a-b|)/2
min(a,b)=(a+b-|a-b|)/2
private static long median(Integer i1, Integer i2, Integer i3) {

    List<Integer> list = Arrays.asList(
            i1 == null ? 0 : i1,
            i2 == null ? 0 : i2,
            i3 == null ? 0 : i3);

    Collections.sort(list);
    return list.get(1);
}
但是,当使用浮点操作时,这是不正确的,因为需要精确的最小值/最大值,而不是接近它的值。幸运的是,浮点最小值/最大值在硬件中已经支持了很长时间(在x86上,从奔腾III开始)了。

这一个可以工作:

template<typename T> T median3_1_gt_2(const T& t1, const T& t2, const T& t3) {
    if (t3>t1) {
        return t1;
    } else {
        return std::max(t2, t3);
    }
}
template<typename T> T median3(const T& t1, const T& t2, const T& t3) {
    if (t1>t2) {
        return median3_1_gt_2(t1, t2, t3);
    } else {
        return median3_1_gt_2(t2, t1, t3);
    }
}
模板T介质3\u 1\u gt\u 2(常数T&t1、常数T&t2、常数T&t3){
如果(t3>t1){
返回t1;
}否则{
返回标准::最大值(t2,t3);
}
}
模板T中间层3(常数T&t1、常数T&t2、常数T&t3){
如果(t1>t2){
返回介质3_1_gt_2(t1、t2、t3);
}否则{
返回介质3_1_gt_2(t2、t1、t3);
}
}
if(数组[aIndex]>数组[bIndex]){
if(array[bIndex]>array[cIndex])返回bIndex;
if(array[aIndex]>array[cIndex])返回cIndex;
返回aIndex;
}否则{
if(array[bIndex]
这里有一个答案,使用min/max和no分支()。实际上,4个min/max操作就足以找到中间值,不需要xor:

median = max(min(a,b), min(max(a,b),c));
虽然,它不会给你中值的指数

所有个案的分项数字:

a b c
1 2 3   max(min(1,2), min(max(1,2),3)) = max(1, min(2,3)) = max(1, 2) = 2
1 3 2   max(min(1,3), min(max(1,3),2)) = max(1, min(3,2)) = max(1, 2) = 2
2 1 3   max(min(2,1), min(max(2,1),3)) = max(1, min(2,3)) = max(1, 2) = 2
2 3 1   max(min(2,3), min(max(2,3),1)) = max(2, min(3,1)) = max(2, 1) = 2
3 1 2   max(min(3,1), min(max(3,1),2)) = max(1, min(3,2)) = max(1, 2) = 2
3 2 1   max(min(3,2), min(max(3,2),1)) = max(2, min(3,1)) = max(2, 1) = 2

还有一个想法。有三个数字
{a,b,c}
。然后:

middle = (a + b + c) - min(a,b,c) - max(a,b,c);

当然,我们必须记住数字限制…

您可以使用数组,如下所示:

if (array[randomIndexA] > array[randomIndexB]) {
  if (array[randomIndexB] > array[randomIndexC]) {
    return "b is the middle value";
  } else if (array[randomIndexA] > array[randomIndexC]) {
    return "c is the middle value";
  } else {
    return "a is the middle value";
  }
} else {
  if (array[randomIndexA] > array[randomIndexC]) {
    return "a is the middle value";
  } else if (array[randomIndexB] > array[randomIndexC]) {
    return "c is the middle value";
  } else {
    return "b is the middle value";
  }
}
max(a,b)=(a+b+|a-b|)/2
min(a,b)=(a+b-|a-b|)/2
private static long median(Integer i1, Integer i2, Integer i3) {

    List<Integer> list = Arrays.asList(
            i1 == null ? 0 : i1,
            i2 == null ? 0 : i2,
            i3 == null ? 0 : i3);

    Collections.sort(list);
    return list.get(1);
}
私有静态长中位数(整数i1、整数i2、整数i3){
List=Arrays.asList(
i1==null?0:i1,
i2==null?0:i2,
i3==null?0:i3);
集合。排序(列表);
返回列表。获取(1);
}

基于Gyorgy的优秀答案,您可以通过使用条件移动替换最小/最大值来获得无分支的中值指数:

int i = (array[A] >= array[B]) ? A : B;
int j = (array[A] <= array[B]) ? A : B;
int k = (array[i] <= array[C]) ? i : C;
int median_idx = (array[j] >= array[k]) ? j : k;
inti=(数组[A]>=array[B])?A:B;
int j=(数组[A]
中值=(A+b+c)-Math.min(Math.min(A,b),c)-Math.max(Math.max(A,b),c)


这是最基本的一个,我不知道它的效率有多高,但这些函数毕竟使用if条件。如果您愿意,可以将此语句转换为if-else语句,但这需要时间。为什么这么懒?

我没有看到实现交换的解决方案:

int middle(int a, int b, int c) {
    // effectively sort the values a, b & c
    // putting smallest in a, median in b, largest in c

    int t;

    if (a > b) {
        // swap a & b
        t = a;
        a = b;
        b = t;
    }

    if (b > c) {
        // swap b & c
        t = b;
        b = c;
        c = t;

        if (a > b) {
            // swap a & b
            t = a;
            a = b;
            b = t;
        }
    }

    // b always contains the median value
    return b;
}
maximust=(a>b)和&(a>c)?a:(b>c?b:c);
最小值=(a方法1

int a,b,c,result;
printf("enter three number");
scanf("%d%d%d",&a,&b,&c);
result=a>b?(c>a?a:(b>c?b:c)):(c>b?b:(a>c?a:c));
printf("middle %d",result);
方法2

int a=10,b=11,c=12;
//Checking for a is middle number or not
if( b>a && a>c || c>a && a>b )
{
    printf("a is middle number");
}

//Checking for b is middle number or not
if( a>b && b>c || c>b && b>a )
{
    printf("b is middle number");
}

//Checking for c is middle number or not
if( a>c && c>b || b>c && c>a )
{
    printf("c is middle number");
}
方法3

if(a>b)
{
    if(b>c)
    {
        printf("b is middle one");
    }
    else if(c>a)
    {
        printf("a is middle one");
    }
    else
    {
        printf("c is middle one");
    }
}
else
{
    if(b<c)
    {
        printf("b is middle one");
    }
    else if(c<a)
    {
        printf("a is middle one");
    }
    else
    {
        printf("c is middle one");
    }
}
if(a>b)
{
如果(b>c)
{
printf(“b是中间的一个”);
}
如果(c>a),则为else
{
printf(“a是中间的一个”);
}
其他的
{
printf(“c是中间的
int min(const int a, const int b) { const int d = b - a; return a + (d & (d >> 31)); }
int max(const int a, const int b) { const int d = a - b; return a - (d & (d >> 31)); }
int median2(int a, int b, int c) {
    return (a > b) ^ (a > c) ? a : (a > b) ^ (b > c) ? c : b;
}
public static void main(String[] args) {

    System.out.println(median(3, 6, 9));
    System.out.println(median(3, 9, 6));
    System.out.println(median(6, 3, 9));
    System.out.println(median(6, 9, 3));
    System.out.println(median(9, 3, 6));
    System.out.println(median(9, 6, 3));
    System.out.println(median(6, 6, 3));
    System.out.println(median(6, 6, 9));
    System.out.println(median(6, 3, 6));
    System.out.println(median(6, 9, 6));
    System.out.println(median(3, 6, 6));
    System.out.println(median(9, 6, 6));
    System.out.println(median(6, 6, 6));

}
   | 00  01  11  10 (p, q)
---+----------------------
 0 |  b   c   *   a
 1 |  *   a   b   c
(s)|
   |  0   1 (t)
---+---------
 0 |  b   c  
 1 |  *   a  
(u)|
private static int median(int a, int b, int c) {
    boolean t = (a > b) ^ (b > c);
    boolean u = (a > b) ^ (a > c);
    if (u)
        return a;
    else if (t)
        return c;
    else
        return b;
}
int median2(int a, int b, int c) {
    return (a > b) ^ (a > c) ? a : (a > b) ^ (b > c) ? c : b;
}
// Compute median of three values, no branches

int median3(int V[3])
{
  unsigned int A,B,C;
  
  A=(V[0] < V[1]);
  B=(V[1] < V[2]);
  C=(V[0] < V[2]);

  return V[(B^C)<<1 | (A^B^1)];
  
}
int middle(int A, int B, int C) {
      return (A>B&&A>C)?B>C?B:C:(B>C&&B>A)?A>C?A:C:B;
}