对于大小为N的数组,需要多少比较次数?
对于大小为N的数组,需要多少比较次数?
最优算法需要n+log n-2次比较。把元素当作参赛者,接下来进行锦标赛排序。
首先像树一样比较这些元素。
|
/ \
| |
/ \ / \
x x x x
这需要n-1次比较,每个元素最多参与log n次比较。你将找到最大的元素作为获胜者。你可以通过最多2·(N-1)次比较和两个变量来找到第二大的值,这两个变量分别保存最大值和第二大值:
largest := numbers[0];
secondLargest := null
for i=1 to numbers.length-1 do
number := numbers[i];
if number > largest then
secondLargest := largest;
largest := number;
else
if number > secondLargest then
secondLargest := number;
end;
end;
end;
使用冒泡排序或选择排序算法以降序对数组进行排序。不要完全排序数组,只需两次遍历。第一次遍历得出最大元素,第二次遍历将给出第二个最大元素。
第一次遍历的比较次数:n-1
第二次遍历的比较次数:n-2
查找第二大元素的总比较次数:2n-3
也许您可以概括这个算法。如果您需要第三个最大元素,则进行三次遍历。
通过上述策略,您不需要任何临时变量,因为冒泡排序和选择排序是就地排序算法。
2n-3
。 - Rajat Saxena这里是一些代码,可能不是最优的,但至少可以找到第二大的元素:
if( val[ 0 ] > val[ 1 ] )
{
largest = val[ 0 ]
secondLargest = val[ 1 ];
}
else
{
largest = val[ 1 ]
secondLargest = val[ 0 ];
}
for( i = 2; i < N; ++i )
{
if( val[ i ] > secondLargest )
{
if( val[ i ] > largest )
{
secondLargest = largest;
largest = val[ i ];
}
else
{
secondLargest = val[ i ];
}
}
}
如果数组中最大的两个元素位于开头,则至少需要N-1次比较,最坏情况下最多需要2N-3次比较(前两个元素中的一个是数组中最小的元素)。
Gumbo算法的PHP版本: http://sandbox.onlinephpfunctions.com/code/51e1b05dac2e648fd13e0b60f44a2abe1e4a8689
$numbers = [10, 9, 2, 3, 4, 5, 6, 7];
$largest = $numbers[0];
$secondLargest = null;
for ($i=1; $i < count($numbers); $i++) {
$number = $numbers[$i];
if ($number > $largest) {
$secondLargest = $largest;
$largest = $number;
} else if ($number > $secondLargest) {
$secondLargest = $number;
}
}
echo "largest=$largest, secondLargest=$secondLargest";
take temp array
temp = [0,0], int dummmy=0;
for (no in inPutArray) {
if(temp[1]<no)
temp[1] = no
if(temp[0]<temp[1]){
dummmy = temp[0]
temp[0] = temp[1]
temp[1] = temp
}
}
print("Second largest no is %d",temp[1])
第一种情况--> 9 8 7 6 5 4 3 2 1
第二种情况--> 50 10 8 25 ........
第三种情况--> 50 50 10 8 25.........
第四种情况--> 50 50 10 8 50 25.......
public void second element()
{
int a[10],i,max1,max2;
max1=a[0],max2=a[1];
for(i=1;i<a.length();i++)
{
if(a[i]>max1)
{
max2=max1;
max1=a[i];
}
else if(a[i]>max2 &&a[i]!=max1)
max2=a[i];
else if(max1==max2)
max2=a[i];
}
}
抱歉,JS代码...
已测试两个输入:
a = [55,11,66,77,72];
a = [ 0, 12, 13, 4, 5, 32, 8 ];
var first = Number.MIN_VALUE;
var second = Number.MIN_VALUE;
for (var i = -1, len = a.length; ++i < len;) {
var dist = a[i];
// get the largest 2
if (dist > first) {
second = first;
first = dist;
} else if (dist > second) { // && dist < first) { // this is actually not needed, I believe
second = dist;
}
}
console.log('largest, second largest',first,second);
largest, second largest 32 13
我知道这是一个老问题,但这是我解决它的尝试,利用了锦标赛算法。它类似于@sdcvvc使用的解决方案,但我使用二维数组存储元素。
为了使事情正常运行,有两个假设:
1)数组中的元素数量是2的幂
2)数组中没有重复项
整个过程包括两个步骤:
1.通过比较两个元素来构建一个二维数组。第一行在二维数组中将是整个输入数组。下一行包含上一行比较的结果。我们在新构建的数组上继续比较并继续构建二维数组,直到达到仅包含一个元素(最大元素)的数组。
2.我们有一个二维数组,其中最后一行仅包含一个元素:最大元素。我们继续从底部到顶部进行,在每个数组中找到被最大值“打败”的元素,并将其与当前的“第二大”值进行比较。要找到被最大值击败的元素,并避免O(n)比较,我们必须存储前一行中最大元素的索引。这样,我们可以轻松检查相邻元素。在任何级别(高于根级别),相邻元素的获取方式为:
leftAdjacent = rootIndex*2
rightAdjacent = rootIndex*2+1,
rootIndex 是上一层中最大(根)元素的索引。
我知道这个问题要求使用 C++,但是这是我在 Java 中尝试解决它的方法。(我使用了列表而不是数组,以避免混乱的更改数组大小和/或不必要的数组大小计算。)
public static Integer findSecondLargest(List<Integer> list) {
if (list == null) {
return null;
}
if (list.size() == 1) {
return list.get(0);
}
List<List<Integer>> structure = buildUpStructure(list);
System.out.println(structure);
return secondLargest(structure);
}
public static List<List<Integer>> buildUpStructure(List<Integer> list) {
List<List<Integer>> newList = new ArrayList<List<Integer>>();
List<Integer> tmpList = new ArrayList<Integer>(list);
newList.add(tmpList);
int n = list.size();
while (n>1) {
tmpList = new ArrayList<Integer>();
for (int i = 0; i<n; i=i+2) {
Integer i1 = list.get(i);
Integer i2 = list.get(i+1);
tmpList.add(Math.max(i1, i2));
}
n/= 2;
newList.add(tmpList);
list = tmpList;
}
return newList;
}
public static Integer secondLargest(List<List<Integer>> structure) {
int n = structure.size();
int rootIndex = 0;
Integer largest = structure.get(n-1).get(rootIndex);
List<Integer> tmpList = structure.get(n-2);
Integer secondLargest = Integer.MIN_VALUE;
Integer leftAdjacent = -1;
Integer rightAdjacent = -1;
for (int i = n-2; i>=0; i--) {
rootIndex*=2;
tmpList = structure.get(i);
leftAdjacent = tmpList.get(rootIndex);
rightAdjacent = tmpList.get(rootIndex+1);
if (leftAdjacent.equals(largest)) {
if (rightAdjacent > secondLargest) {
secondLargest = rightAdjacent;
}
}
if (rightAdjacent.equals(largest)) {
if (leftAdjacent > secondLargest) {
secondLargest = leftAdjacent;
}
rootIndex=rootIndex+1;
}
}
return secondLargest;
}
以下解决方案需要进行2(N-1)次比较:
arr #array with 'n' elements
first=arr[0]
second=-999999 #large negative no
i=1
while i is less than length(arr):
if arr[i] greater than first:
second=first
first=arr[i]
else:
if arr[i] is greater than second and arr[i] less than first:
second=arr[i]
i=i+1
print second