遍历数组以找到线性时间中的第二大元素

时间:2011-04-12 06:19:44

标签: c++ c algorithm

在线性时间内是否有一种方法可以找到哪个是数组的第二大元素? 数组元素可以是正数,负数或零。 元素可以重复。 没有STL允许。 可以使用Python。

解决方案:对数组进行排序并获取第二个元素但排序不允许

修改:根据定义,第二大元素将是数值上较小的元素。就像我们有

Arr = {5,5,4,3,1} 然后第二大是4

加成 让我们说如果我想将问题概括为kth最大且复杂度小于线性,如nlogn,那么解决方案是什么。

9 个答案:

答案 0 :(得分:8)

浏览数组,保留2个内存插槽,记录到目前为止看到的2个最大元素。返回两者中较小的一个。

....对于这个我看不到的问题有什么棘手的问题吗?

答案 1 :(得分:6)

你可以,这是伪算法:

max = 2max = SMALLEST_INT_VALUE;

for element in v:
   if element > max:
      2max = max;
      max = element;

  else if element > 2max:
      2max = element;

2max是您要寻找的值。

对于特定情况,算法不会返回正确的值,例如其元素相等的数组。

答案 2 :(得分:4)

如果你想要一个真正的O(n)算法,并且想要在数组中找到第n个最大的元素,那么你应该使用quickselect(它基本上是quicksort,你扔掉你不感兴趣的分区),以及下面的是一个很好的写作,运行时分析:

http://pine.cs.yale.edu/pinewiki/QuickSelect

答案 3 :(得分:2)

  • 创建一个大小为3的临时数组
  • 复制前3个元素,
  • 对临时数组进行排序,
  • 使用源数组中的第4个元素
  • 替换临时数组中的最后一个
  • 对临时数组进行排序,
  • 使用源数组中的第5个元素
  • 替换临时数组中的最后一个元素
  • 对临时数组进行排序,

对大小为3的数组进行排序是恒定时间,对源数组的每个元素执行一次,因此线性总时间。

答案 4 :(得分:2)

伪代码:

int max[2] = { array[0], array[1] }

if(max[1] < max[0]) swap them

for (int i = 2; i < array.length(); i++) {
  if(array[i] >= max[0]) max[1] = max[0]; max[0] = array[i]
  else if(array[i] >= max[1]) max[1] = array[i];
}

现在,max数组包含最多2个元素。

答案 5 :(得分:1)

是的。你把它标记为C / C ++,但你提到你可以用Python做到这一点。无论如何,这是算法:

  1. 创建数组(显然)。
  2. 如果第一项大于第二项,请将第一个变量设置为第一个项目,将第二个变量设置为第二个项目。否则,反其道而行。
  3. 遍历所有项目(前两项除外)。
  4. 如果数组中的项大于第一个变量,则将第二个变量设置为第一个变量,将第一个变量设置为该项。否则,如果项目大于第二个变量,则将第二个变量设置为项目。
  5. 第二个变量是你的答案。

    list = [-1,6,9,2,0,2,8,10,8,-10]
    
    if list[0] > list[1]:
            first = list[0]
            second = list[1]
    else:
            first = list[1]
            second = list[0]
    
    for i in range(2, len(list)):
            if list[i] > first:
                    first, second = list[i], first
            elif list[i] > second:
                    second = list[i]
    
    print("First:", first)
    print("Second:", second)
    

答案 6 :(得分:1)

// assuming that v is the array and length is its length
int m1 = max(v[0], v[1]), m2 = min(v[0], v[1]);

for (int i=2; i<length; i++) {
  if (likely(m2 >= v[i]))
    continue;
  if (unlikely(m1 < v[i]))
    m2 = m1, m1 = v[i];
  else
    m2 = v[i];
}

您需要的结果是m2(出于性能目的,可能并且不太可能将宏定义为here,如果您不需要它们,可以直接删除它们。)

答案 7 :(得分:0)

我认为其他答案没有说明在像[0,1,1]这样的数组中,第二大的数字是0(根据更新的问题定义)。此外,所有提到的quickselect都不是O(n)而是O(n ^ 2)并且正在做更多的工作而不是必要的(最重要的是问题陈述不允许的排序算法)。这是一个非常类似于Simone的算法,但更新后返回第二大的唯一元素:

def find_second(numbers):
    top = numbers[0]
    second = None

    for num in numbers[1:]:
        if second is None:
            if num < top: second = num
            elif num > top:
                second = top
                top = num
        else:
            if num > second:
                if num > top:
                    second = top
                    top = num
                elif num < top: second = num

    if second is not None: return second
    return top

if __name__ == '__main__':
    print "The second largest is %d" % find_second([1,2,3,4,4,5,5])

答案 8 :(得分:0)

// Second larger element and its position(s)
    int[] tab = { 12, 1, 21, 12, 8, 8, 1 };
    int[] tmp = Arrays.copyOf(tab, tab.length);
    int secMax = 0;
    Arrays.sort(tmp);
    secMax = tmp[tmp.length - 2];
    System.out.println(secMax);
    List<Integer> positions = new ArrayList<>();
    for (int i = 0; i < tab.length; i++) {
        if (tab[i] == secMax) {
            positions.add(i);
        }
    }
    System.out.println(positions);