在整数列表C#中查找倒数第二个最大元素

时间:2018-04-10 07:07:28

标签: c# .net

我有一个

list<int> input = //from db of one million records
<100> 记录。

虽然我知道使用input.OrderByDescending().Skip(1).Take(1)可以解决问题,但如果我有100万条记录,那么使用OrderBY不是最佳做法。

在这种情况下,当我们有更多记录时,哪种解决方案最好?

4 个答案:

答案 0 :(得分:4)

在跟踪max以及max2时扫描列表,您将获得O(N)O(N * log(N))时间复杂度:

  // Maximum value
  int max  = Math.Max(input[input.Count - 1], input[input.Count - 2]);
  // Second greatest   
  int max2 = Math.Min(input[input.Count - 1], input[input.Count - 2]);

  // i >= 0: Comparing with 0 is slightly faster then with Count
  for (int i = input.Count - 3; i >= 0; --i) {
    int v = input[i];

    if (v >= max) {
      max2 = max;
      max = v; 
    }
    else if (v > max2) 
      max2 = v;
  }

修改:如果重复忽略(请参阅下面的评论),因此[1, 2, 3, 4, 4, 4, 4]的答案应为{ {1}},而不是3

4

答案 1 :(得分:2)

你可以通过跟踪下一个最大值并在列表中迭代一次来完成。

DROP LOGIN [XXXXXX\user10]

答案 2 :(得分:2)

如果您的列表仅包含不同的值,您还可以执行以下操作:

var max = input.Max();
input.Remove(max);
var result = input.Max();

答案 3 :(得分:0)

这是一个只使用LINQ和C#7元组迭代一次的解决方案:

var input = Enumerable.Range(0, 101);

var topTwo = input.Aggregate((Biggest: Int32.MinValue, SecondBiggest: Int32.MinValue),
                             (acc, next) =>
                             {
                                 if (next > acc.Biggest)
                                 {
                                     acc.SecondBiggest = acc.Biggest;
                                     acc.Biggest = next;
                                 }

                                 if (next < acc.Biggest && next > acc.SecondBiggest)   
                                     acc.SecondBiggest = next;

                                 return acc;
                             });

WriteLine(topTwo.SecondBiggest);  // 99