数组中的第三个最小元素

时间:2013-07-11 17:44:23

标签: java arrays algorithm

我编写了一个方法来查找数组中的第二个最小数字而不使用sort 。我想我可以扩展相同的逻辑来找到数组中的第三个最小数字。但是我意识到它是不是那么容易。我的大脑必须因缺乏睡眠或其他东西而变得愚蠢。我的代码是findSecondSmallest和findThirdSmallest ..有人可以纠正我逻辑中的缺陷吗?

public class ArrayElementSelection{
    public static int findSecondSmallest(int[] a){
            int N = a.length;
            int min = 0;
            int secondSmallest = 0;
            for(int i=1;i<N;i++){
                if(a[i] < a[min]){
                    secondSmallest = min;
                    min = i;

                }else if(a[i] < a[secondSmallest]){
                    secondSmallest = i;
                }
            }
            return a[secondSmallest];
        }

    public static int findThirdSmallest(int[] a){
            int N = a.length;
            int min = 0;
            int secondSmallest = 0;
            int thirdSmallest = 0;
            for(int i=1;i<N;i++){
                if(a[i] < a[min]){
                    min = i;
                }else if(a[i] < a[secondSmallest]){
                    secondSmallest = i;
                }else if(a[i]< a[thirdSmallest]){
                    thirdSmallest = i;
                }
            }

            return a[thirdSmallest];
        }

    public static void main(String[] args) {
         int[] a = new int[]{4,2,3,1,5};
         System.out.println(findThirdSmallest(a));
    }
}

>> 4

9 个答案:

答案 0 :(得分:3)

更新三个值中的一个时,您可能还需要更新其他值。

如果你有一个新的最小值,那么之前的最小值现在是第二低......等等。

在同一推理线上,我怀疑你的第二个最低的例子对所有数组都不起作用。

运行您的示例(或手动运行逻辑,更简单),在类似的数组上运行:[5,4,3,2,1]

你最终会将最小值指向正确的位置,而第二个/第三个值仍然指向0.当你找到一个要保留的新值时,你基本上需要“移动”上面的值。

答案 1 :(得分:3)

好的,让我们清理一下。我们想要找到数组中的第三个最小元素。

    NavigableSet<Integer> min3 = new TreeSet<Integer>();
    //We keep only 3 elements in min3, as soon as the set size grows over 3
    //we remove the last element, which is the max.

    for (int x : array) {
        min3.add(x);
        if (min3.size() > 3) {
            min3.pollLast();
        } 
    }

    if (array.length >= 3) {
        Integer thirdMinimum = min3.pollLast();
        System.out.println(thirdMimimum);
    } else {
       //array must contain at least 3 elements
    }

上面的代码段找到了第三个唯一的最小值。如果我们保留一个排序的整数列表,而不是一组整数。我们可以找到第三个非唯一的最小值。

答案 2 :(得分:2)

这是找到数组中3个最小项的逻辑。假设您的源数组有100个元素。使用3个元素创建一个名为temp的新数组,并立即将源数组中的前3个元素添加到其中,然后对其进行排序(对3元素数组进行排序)。标记temp中最大元素的大小,将其命名为maxTemp。

现在开始从第4个元素循环到整个源数组。如果找到比maxTemp小的元素:

1)确定这个新值适合的临时数组中的位置,然后将其放入并相应地移动较大的值。摆脱之前的maxTemp,因为它现在太大而无法获得资格。

2)设置新的maxTemp

3)继续循环

完成后,您将拥有包含3个最小元素的临时数组。

答案 3 :(得分:2)

有一种通用的方法:使用优先级队列。

  • 创建一个优先级队列,其中最大的项目首先出列
  • 现在迭代列表中的项目,将它们添加到优先级队列中
  • 每当优先级队列超过k个项目时,将项目出列
  • 完成迭代后,第k个最小项目位于优先级队列的前面

优先级队列操作需要O(log(X))次,其中X是队列中的项目数。由于我们的优先级队列不超过k,因此每个操作都需要O(log(k))次。如果您通过设置O(n log(k))使O(n)成为常量,整个过程将花费k时间,k=3

答案 4 :(得分:1)

可能不是最好的方法,但要扩展你的第一个例子如何工作我相信它会是这样的:

public static int findThirdSmallest(int[] a){
        int N = a.length;
        int min = 0;
        int secondSmallest = 1;
        int thirdSmallest = 2;
        for(int i=1;i<N;i++){
            if(a[i] < a[min]){
                thirdSmallest = secondSmallest;
                secondSmallest = min;
                min = i;
            }
        }
        return a[thirdSmallest];
    }

如果数组长度小于3,那就会有错误,但除此之外我认为它应该有用。

编辑:实际上看你的算法是不正确的,我不相信有任何方法可以获得第n个最小的数字,而只需要通过数组只有1次,天真地你需要通过找到min,然后再次检查并与min进行比较以找到下一个数字,依此类推。我天真地说,因为这对于获得第n个最小元素有着糟糕的表现,但它会完成工作。

答案 5 :(得分:1)

让我们假设您在单次通过数组时处于中途。到目前为止,您拥有最小,第二小和第三小的数字。

您看到的下一个数字可能是新的最小,第二小或第三小,所以您的程序必须处理这个问题。

这是一个通常在一个通道中执行此操作的示例。您只需更改第一个参数,就可以使用相同的方法查找最小,第二小或第十小。复杂度为O(n * m),其中n是数组的大小,m是您想要得到的元素的顺序(例如,对于第三个最小,m是3):

public class Smallest {

/**
 * Returns the index of the "pos"th smallest element.
 * 
 * @param pos
 *            Which element to return
 * @param a
 *            The array to search
 * @return -1 if there are less than pos elements
 */
public static int findSmallest(int pos, int[] a) {
    int i, j;

    // Keep an array of "pos" elements.
    List<Integer> smallest = new ArrayList<Integer>(3);

    // Init with -1 to indicate we haven't found an element yet.
    for (i = 0; i < pos; i++) smallest.add(i, -1);

    // Search for the smallest "pos" elements.
    for (i = 0; i < a.length; i++) {
        // See where in our smallest array, this element goes.
        for (j = 0; j < pos; j++) {
            Integer spos = smallest.get(j);
            if ((spos == -1) || (a[i] < a[spos])) {
                // The current element a[i] is the "j+1"th smallest.
                smallest.add(j, i);
                smallest.remove(3);
                break;
            } // if ((spos == -1) || (a[i] < a[spos]))
        } // for (j = 0; j < pos; j++)
    } // for (i = 0; i < a.length; i++) 
    return smallest.get(pos-1);
}

/**
 * @param args
 */
public static void main(String[] args) {
    // Find the 3rd smallest in the set.
    int a[] = {9,3,4,8,1,2,5,7,6};
    int thirdSmallest = findSmallest(3, a);
    System.out.println("Third smallest is a[" + thirdSmallest +"]="+a[thirdSmallest]);
}
}

答案 6 :(得分:0)

我发现这很有意思,所以我很快写了一个小的递归方法来解决它。这解决了给定的第N个最小元素(一个整数数组,第N个最小数字和0(一个起始参考))

public class Thir {
    public static void main(String[] args) {
      int[] a = new int[]{4,2,3,1,5};
      System.out.println(findNthSmallest(a,3,0));
    }

    static int findNthSmallest(int [] array, int n, int last) {
      if (n == 0)
        return last;
      int MAX = 9999;
      int pos = 0;
      int curMin = 0;
      boolean changed = false;
      for (int i = 0; i < array.length; i++)
      {
        if (changed == false && array[i] > last)
         {
          curMin = array[i];
          changed = true;
         }
        if (array[i] < curMin)
        {
          pos = i;
          curMin = array[i];
        }
      }
      array[pos] = MAX;
      return findNthSmallest(array, n-1, curMin);
    }
}

答案 7 :(得分:0)

你只需要使用一些优先级队列或TreeSet来获得时间N * log N中的第X个最小或最大元素,否则你在N * M时间内做,这太糟糕了考虑。

在遍历数组时基本创建TreeSet并将项目放入其中,然后在完成后 - 您可以简单地遍历TreeSet,迭代器下的第N个项目是您正在寻找的。

答案 8 :(得分:0)

public int thirdSmallest(Int[] arr){

    for(int x = 0; x < arr.length; x++){
       for(int y = 0; y < arr.length; y++){
           if(arr[x] > arr[y]){
             int z = arr[x];
             arr[x] = arr[y];
             arr[y] = z;
           }
       }       
    }
  return arr[2]; //third smallest
}