我编写了一个方法来查找数组中的第二个最小数字而不使用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
答案 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)
有一种通用的方法:使用优先级队列。
优先级队列操作需要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个项目是您正在寻找的。 p>
答案 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
}