Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding two minimum values out of four?

Tags:

c

algorithm

So, I have four integers and I need to find out the lowest two out of those four. What would be the most efficient way of doing so in C (or any other language)?

Edit: I need a fixed implementation, for the sake of efficiency as this is a very critical operation that is going to be performed thousands of times.

like image 727
Kristina Brooks Avatar asked Aug 31 '12 11:08

Kristina Brooks


5 Answers

Here's an efficient implementation using sorting networks:

inline void Sort2(int *p0, int *p1)
{
    if (*p0 > *p1)
    {
        const int temp = *p0;
        *p0 = *p1;
        *p1 = temp;
    }
}

inline void Sort4(int *p0, int *p1, int *p2, int *p3)
{
    Sort2(p0, p1);
    Sort2(p2, p3);
    Sort2(p0, p2);  
    Sort2(p1, p3);  
    Sort2(p1, p2);  
}

This takes only 5 compares and up to 5 swaps. You can just ignore the results for p2, p3.

Note that for a performance-critical application Sort2 can be implemented without branches in one or two instructions on some architectures.

like image 95
Paul R Avatar answered Nov 15 '22 07:11

Paul R


Just write a loop and keep track of the lowes 2 values ? Should be at max O(2N) which is i think the best achievable complexity.

like image 21
Minion91 Avatar answered Nov 15 '22 07:11

Minion91


The most efficient way? Trying to avoid any extra steps, I got this (in pseudo-code). This will avoid any unnecessary comparisons that you'll get with other more general solutions (specifically ones that don't advantage of the transitive nature of comparison operations).

Bear in mind that this is only thinking about efficiency, not at all aiming for beautiful code.

if a<=b:
  if b<=c:
    # c too big, which of b and d is smaller?
    if b<=d:
      return (a,b)
    else:
      return (a,d)
  else if b<=d:
    # a and c both < b, and b < d
    return (a,c)
  else:
    # b is > a, c and d. Down to just those three.
    if a<=c:
      if c<=d:
        # a < c < d
        return (a,c)
      else:
        # a and d both < c
        return (a,d)
    else if d<=a:
      # Both c and d < a
      return (c,d)
    else:
      # c < a < d
      return (a,c)
else:
  # b < a
  if a<=c:
    # c too big, which of a and d is smaller?
    if a<=d:
      return (a,b)
    else:
      return (b,d)
  else if a<=d:
    # b and c both < a, and a < d
    return (b,c)
  else:
    # a is > b, c and d. Down to just those three.
    if b<=c:
      if c<=d:
        # b < c < d
        return (b,c)
      else:
        # b and d both < c
        return (b,d)
    else if d<=b:
      # Both c and d < b
      return (c,d)
    else:
      # c < b < d
      return (b,c)

I think this has a worst case of 5 comparisons and a best case of 3 (obviously there's no way of doing it in less than 3 comparison).

like image 21
hcarver Avatar answered Nov 15 '22 07:11

hcarver


You can get away with exactly 4 comparisons and maximally 4 swaps.

inline void swap(int* i, int* j) {
  static int buffer;
  buffer = *j;
  *j = *i;
  *i = buffer;
}

inline void sort2(int* a, int* s) {
  if (*s < a[1])
    swap(s,a+1);
  if (*s < a[0]) // it is NOT sufficient to say "else if" here
    swap(s,a);
}

inline void sort4(int* a) {
  sort2(a,a+2);
  sort2(a,a+3);
}

The result will be sitting the the first to cells, but note that these cells are not necessarily sorted! They're just the smallest elements.

like image 34
bitmask Avatar answered Nov 15 '22 07:11

bitmask


I would make an array out of them, sort and take the first two values.

like image 44
CharlesB Avatar answered Nov 15 '22 05:11

CharlesB