【问题标题】:Find the 2nd largest element in an array with minimum number of comparisons查找数组中具有最少比较次数的第二大元素
【发布时间】:2011-04-07 10:07:50
【问题描述】:

对于一个大小为 N 的数组,需要比较多少次?

【问题讨论】:

  • 您允许多少临时存储空间?
  • @Sachin,这将是 n*log(n) 比较。排序无法变得更快。
  • @Stargazer712:除非数组是整数。然后你可以进行基数排序,根本没有比较;-)
  • @Steve:即便如此,假设您知道整数的上下界:)。基数排序非常有用,但非常受限制。当问题中没有给出这样的约束时,最好假设 n*log(n)
  • @Stargazer712:不需要边界:en.wikipedia.org/wiki/…。想一想,基数排序仍然涉及循环输入数据,并且循环必须涉及终止条件中的比较。不过,它不必是 order 比较,只是相等比较。但你是对的,这个问题没有说明数据类型,所以正确的答案必须假设不透明数据和比较器函数。如果面试官错误地提出了int 特殊情况(或真正推送时的字符串),则为 0 比较......

标签: arrays algorithm search


【解决方案1】:

最佳算法使用 n+log n-2 次比较。将元素视为竞争对手,锦标赛将对它们进行排名。

首先,比较元素,就像在树中一样

   |
  / \
 |   |
/ \ / \
x x x x

这需要 n-1 次比较,每个元素最多参与比较 log n 次。您将找到最大的元素作为获胜者。

第二大元素一定输给了获胜者(他不能输给其他元素),所以他是获胜者对抗的 log n 个元素之一。您可以使用 log n - 1 比较找到它们中的哪一个。

最优性是通过对手论证证明的。见https://math.stackexchange.com/questions/1601http://compgeom.cs.uiuc.edu/~jeffe/teaching/497/02-selection.pdfhttp://www.imada.sdu.dk/~jbj/DM19/lb06.pdfhttps://www.utdallas.edu/~chandra/documents/6363/lbd.pdf

【讨论】:

  • @Jatin:不,总共需要N+log N-2:N-1次比较找到最大值,log N-1次比较找到log N中丢失的最大元素到最大元素。
  • Jatin:创建二叉树,并从底部开始填充。叶子是数组的元素。每个内部顶点是其两个子顶点中的最大值。您需要的比较次数是内部顶点的数量,即 n-1。然后,查看最大元素的“对手”,它们是 log N 元素。
  • 所以这涉及到一些空间复杂性,这可以回答我的所有问题:)
  • @POOJA GUPTA:首先,找到最大和第二大元素(如我的回答);这给出了一个 logn 项。第 3 大元素必须丢失第 1 或第 2 元素,因此您需要检查丢失与第 1 大元素(即第二个 logn 项)和第 2 个最大元素(即第三个 logn 项)的比较的元素。
  • @Hengameh 老实说,我不明白 8 的原因。需要 (n + log n - 2) 比较才能找到最大和第二大元素,称它们为 L_1 和 L_2;接下来,我们找到输给L_1的最大元素,不是L_2,有log n-1个候选,这意味着log n-2个比较,接下来,我们找到最大的输给L_2的元素,有log n-2 个候选者,所以记录 n-3 个比较,取这两个中的最大值,这给出 n+log n-2 + log n - 2 + log n - 3 + 1=n+3 log n-6。不过,我可能会遗漏一些东西,对数应该在天花板以下等。
【解决方案2】:

您可以通过最多 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;

【讨论】:

  • 如何通过 2 次比较找到一组 3 个元素中的 2 个最大元素?
  • @sdcvvc:是的,但我猜他的目标是复杂性。那是 O(N)。
  • 您的算法不适用于 {1,3,2}。它会返回 1 而不是 2。
  • -1。你的算法不起作用。在输入“3,5,4”上试一试。
  • @x4u, @Stargazer712:修复了这个问题。
【解决方案3】:

使用冒泡排序或选择排序算法对数组进行降序排序。不要对数组进行完全排序。就两通。第一遍给出最大的元素,第二遍给出第二大的元素。

没有。第一次比较的次数:n-1

没有。第二次比较的次数:n-2

总数查找第二大的比较:2n-3

也许你可以概括这个算法。如果您需要第 3 个最大的,则进行 3 次传球。

通过上述策略,您不需要任何临时变量,因为冒泡排序和选择排序是in place sorting 算法。

【讨论】:

  • 这真是个聪明的解决方案
  • 我很好奇这个解决方案的时间复杂度,因为一个循环只会执行两次。
  • 我的解决方案也是2n-3
【解决方案4】:

这里有一些代码可能不是最优的,但至少实际上找到了第二大元素:

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 ];
        }
    }
}

如果最大的 2 个元素位于数组的开头,则至少需要 N-1 次比较,最坏的情况下最多需要 2N-3 次(前 2 个元素中的一个是数组中的最小元素)。

【讨论】:

    【解决方案5】:

    案例 1-->9 8 7 6 5 4 3 2 1
    案例 2--> 50 10 8 25 ........
    案例 3--> 50 50 10 8 25.........
    案例4--> 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];  
          }  
    }
    

    【讨论】:

      【解决方案6】:

      对不起,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
      

      这应该有最多 a.length*2 比较并且只通过列表一次。

      【讨论】:

        【解决方案7】:

        我知道这是一个老问题,但这是我利用锦标赛算法解决它的尝试。和@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;
            }
        

        【讨论】:

        【解决方案8】:

        假设提供的数组是 inPutArray = [1,2,5,8,7,3] 预期 O/P -> 7(第二大)

         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】:

          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";
          

          【讨论】:

            【解决方案10】:

            假设空间无关紧要,这是我能得到的最小空间。最坏情况下需要 2*n 次比较,最好情况下需要 n 次比较:

            arr = [ 0, 12, 13, 4, 5, 32, 8 ]
            max = [ -1, -1 ]
            
            for i in range(len(arr)):
                 if( arr[i] > max[0] ):
                    max.insert(0,arr[i])
                 elif( arr[i] > max[1] ):
                    max.insert(1,arr[i])
            
            print max[1]
            

            【讨论】:

              【解决方案11】:

              试试这个。

              max1 = a[0].
              max2.
              for i = 0, until length:
                if a[i] > max:
                   max2 = max1.
                   max1 = a[i].
                   #end IF
                #end FOR
              return min2.
              

              它应该像一个魅力。复杂度低。

              这是一个java代码。

              int secondlLargestValue(int[] secondMax){
              int max1 = secondMax[0]; // assign the first element of the array, no matter what, sorted or not.
              int max2 = 0; // anything really work, but zero is just fundamental.
                 for(int n = 0; n < secondMax.length; n++){ // start at zero, end when larger than length, grow by 1. 
                      if(secondMax[n] > max1){ // nth element of the array is larger than max1, if so.
                         max2 = max1; // largest in now second largest,
                         max1 = secondMax[n]; // and this nth element is now max.
                      }//end IF
                  }//end FOR
                  return max2;
              }//end secondLargestValue()
              

              【讨论】:

              • 比较次数不是很有效!你扫描整个数组,我觉得比较的次数是n!
              • 您的代码也不正确!如果“secondmax [n] > max2”怎么办?你没有检查这个概率!
              【解决方案12】:

              使用计数排序,然后找到第二大元素,从索引 0 开始到最后。应该至少有 1 个比较,最多 n-1(当只有一个元素时!)。

              【讨论】:

              • 这并没有回答问题,这是关于比较次数的问题。问题在于分析算法,而不仅仅是算法本身。
              【解决方案13】:
              #include<stdio.h>
              main()
              {
                      int a[5] = {55,11,66,77,72};
                      int max,min,i;
                      int smax,smin;
                      max = min = a[0];
                      smax = smin = a[0];
                      for(i=0;i<=4;i++)
                      {
                              if(a[i]>max)
                              {
                                      smax = max;
                                      max = a[i];
                              }
                              if(max>a[i]&&smax<a[i])
                              {
                                      smax = a[i];
                              }
                      }
                      printf("the first max element z %d\n",max);
                      printf("the second max element z %d\n",smax);
              }
              

              【讨论】:

                【解决方案14】:

                sdcvvc 在 C++11 中接受的解决方案。

                #include <algorithm>
                #include <iostream>
                #include <vector>
                #include <cassert>
                #include <climits>
                
                using std::vector;
                using std::cout;
                using std::endl;
                using std::random_shuffle;
                using std::min;
                using std::max;
                
                vector<int> create_tournament(const vector<int>& input) {
                  // make sure we have at least two elements, so the problem is interesting
                  if (input.size() <= 1) {
                    return input;
                  }
                
                  vector<int> result(2 * input.size() - 1, -1);
                
                  int i = 0;
                  for (const auto& el : input) {
                    result[input.size() - 1 + i] = el;
                    ++i;
                  }
                
                  for (uint j = input.size() / 2; j > 0; j >>= 1) {
                    for (uint k = 0; k < 2 * j; k += 2) {
                      result[j - 1 + k / 2] = min(result[2 * j - 1 + k], result[2 * j + k]);
                    }
                  }
                
                  return result;
                }
                
                int second_smaller(const vector<int>& tournament) {
                  const auto& minimum = tournament[0];
                  int second = INT_MAX;
                
                  for (uint j = 0; j < tournament.size() / 2; ) {
                    if (tournament[2 * j + 1] == minimum) {
                      second = min(second, tournament[2 * j + 2]);
                      j = 2 * j + 1;
                    }
                    else {
                      second = min(second, tournament[2 * j + 1]);
                      j = 2 * j + 2;
                    }
                  }
                
                  return second;
                }
                
                void print_vector(const vector<int>& v) {
                  for (const auto& el : v) {
                    cout << el << " ";
                  }
                  cout << endl;
                }
                
                int main() {
                
                  vector<int> a;
                  for (int i = 1; i <= 2048; ++i)
                    a.push_back(i);
                
                  for (int i = 0; i < 1000; i++) {
                    random_shuffle(a.begin(), a.end());
                    const auto& v = create_tournament(a);
                    assert (second_smaller(v) == 2);
                  }
                
                  return 0;
                }
                

                【讨论】:

                  【解决方案15】:

                  我已经浏览了上述所有帖子,但我确信实施锦标赛算法是最好的方法。让我们考虑@Gumbo 发布的以下算法

                  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;
                  

                  如果我们要在数组中找到第二大数字,这非常好。它有 (2n-1) 次比较。但是如果你想计算第三大数字或第 k 大数字怎么办。上述算法不起作用。你要进行另一个程序。

                  所以,我认为锦标赛算法方法是最好的,这里是 link

                  【讨论】:

                    【解决方案16】:

                    以下解决方案需要 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
                    

                    【讨论】:

                      【解决方案17】:

                      可以在 n + ceil(log n) - 2 比较中完成。

                      解决方案: 需要 n-1 次比较才能得到最小值。

                      但为了达到最低限度,我们将建立一个锦标赛,其中每个元素将成对分组。就像网球比赛一样,任何一轮的获胜者都会继续前进。

                      这棵树的高度将是 log n,因为我们每轮都是一半。

                      获得第二个最小值的想法是,它将在上一轮中被最小候选者击败。因此,我们需要在潜在候选人中找到最小值(被最小值击败)。

                      潜在的候选人将是 log n = 树的高度

                      所以,不。使用锦标赛树找到最小值的比较是 n-1 第二个最小值是 log n -1 总和 = n + ceil(log n) - 2

                      这里是 C++ 代码

                      #include <iostream>
                      #include <cstdio>
                      #include <cstdlib>
                      #include <cmath>
                      #include <vector>
                      
                      using namespace std;
                      
                      typedef pair<int,int> ii;
                      
                      bool isPowerOfTwo (int x)
                      {
                        /* First x in the below expression is for the case when x is 0 */
                        return x && (!(x&(x-1)));
                      }
                      // modified
                      int log_2(unsigned int n) {
                          int bits = 0;
                          if (!isPowerOfTwo(n))
                              bits++;
                          if (n > 32767) {
                              n >>= 16;
                              bits += 16;
                          }
                          if (n > 127) {
                              n >>= 8;
                              bits += 8;
                          }
                          if (n > 7) {
                              n >>= 4;
                              bits += 4;
                          }
                          if (n > 1) {
                              n >>= 2;
                              bits += 2;
                          }
                          if (n > 0) {
                              bits++;
                          }
                          return bits;
                      }
                      
                      int second_minima(int a[], unsigned int n) {
                      
                          // build a tree of size of log2n in the form of 2d array
                          // 1st row represents all elements which fights for min
                          // candidate pairwise. winner of each pair moves to 2nd
                          // row and so on
                          int log_2n = log_2(n);
                          long comparison_count = 0;
                          // pair of ints : first element stores value and second
                          //                stores index of its first row
                          ii **p = new ii*[log_2n];
                          int i, j, k;
                          for (i = 0, j = n; i < log_2n; i++) {
                              p[i] = new ii[j];
                              j = j&1 ? j/2+1 : j/2;
                          }
                          for (i = 0; i < n; i++)
                              p[0][i] = make_pair(a[i], i);
                      
                      
                      
                          // find minima using pair wise fighting
                          for (i = 1, j = n; i < log_2n; i++) {
                              // for each pair
                              for (k = 0; k+1 < j; k += 2) {
                                  // find its winner
                                  if (++comparison_count && p[i-1][k].first < p[i-1][k+1].first) {
                                      p[i][k/2].first = p[i-1][k].first;
                                      p[i][k/2].second = p[i-1][k].second;
                                  }
                                  else {
                                      p[i][k/2].first = p[i-1][k+1].first;
                                      p[i][k/2].second = p[i-1][k+1].second;
                                  }
                      
                              }
                              // if no. of elements in row is odd the last element
                              // directly moves to next round (row)
                              if (j&1) {
                                  p[i][j/2].first = p[i-1][j-1].first;
                                  p[i][j/2].second = p[i-1][j-1].second;
                              }
                              j = j&1 ? j/2+1 : j/2;
                          }
                      
                      
                      
                          int minima, second_minima;
                          int index;
                          minima = p[log_2n-1][0].first;
                          // initialize second minima by its final (last 2nd row)
                          // potential candidate with which its final took place
                          second_minima = minima == p[log_2n-2][0].first ? p[log_2n-2][1].first : p[log_2n-2][0].first;
                          // minima original index
                          index = p[log_2n-1][0].second;
                          for (i = 0, j = n; i <= log_2n - 3; i++) {
                              // if its last candidate in any round then there is
                              // no potential candidate
                              if (j&1 && index == j-1) {
                                  index /= 2;
                                  j = j/2+1;
                                  continue;
                              }
                              // if minima index is odd, then it fighted with its index - 1
                              // else its index + 1
                              // this is a potential candidate for second minima, so check it
                              if (index&1) {
                                  if (++comparison_count && second_minima > p[i][index-1].first)
                                      second_minima = p[i][index-1].first;
                              }
                              else {
                                  if (++comparison_count && second_minima > p[i][index+1].first)
                                      second_minima = p[i][index+1].first;
                              }
                              index/=2;
                              j = j&1 ? j/2+1 : j/2;
                          }
                      
                      
                          printf("-------------------------------------------------------------------------------\n");
                          printf("Minimum          : %d\n", minima);
                          printf("Second Minimum   : %d\n", second_minima);
                          printf("comparison count : %ld\n", comparison_count);
                          printf("Least No. Of Comparisons (");
                          printf("n+ceil(log2_n)-2) : %d\n", (int)(n+ceil(log(n)/log(2))-2));
                          return 0;
                      }
                      
                      int main()
                      {
                          unsigned int n;
                          scanf("%u", &n);
                          int a[n];
                          int i;
                          for (i = 0; i < n; i++)
                              scanf("%d", &a[i]);
                          second_minima(a,n);
                          return 0;
                      }
                      

                      【讨论】:

                        【解决方案18】:
                        function findSecondLargeNumber(arr){
                        
                            var fLargeNum = 0;
                            var sLargeNum = 0;
                        
                            for(var i=0; i<arr.length; i++){
                                if(fLargeNum < arr[i]){
                                    sLargeNum = fLargeNum;
                                    fLargeNum = arr[i];         
                                }else if(sLargeNum < arr[i]){
                                    sLargeNum = arr[i];
                                }
                            }
                        
                            return sLargeNum;
                        
                        }
                        var myArray = [799, -85, 8, -1, 6, 4, 3, -2, -15, 0, 207, 75, 785, 122, 17];
                        

                        参考:http://www.ajaybadgujar.com/finding-second-largest-number-from-array-in-javascript/

                        【讨论】:

                          【解决方案19】:

                          一个具有 O(1) 时间复杂度的好方法是使用最大堆。调用 heapify 两次,你就有答案了。

                          【讨论】:

                            【解决方案20】:
                                int[] int_array = {4, 6, 2, 9, 1, 7, 4, 2, 9, 0, 3, 6, 1, 6, 8};
                                int largst=int_array[0];
                                int second=int_array[0];
                                for (int i=0; i<int_array.length; i++){        
                                    if(int_array[i]>largst) { 
                                        second=largst;
                                        largst=int_array[i];
                                    }  
                                    else if(int_array[i]>second  &&  int_array[i]<largst) { 
                                        second=int_array[i];
                                    } 
                                }
                            

                            【讨论】:

                            • 每个人都缺少其他部分的第二个条件。如果数组中的数字大于 second_largest 并且小于当前 maximum_number,则在哪里比较它。
                            【解决方案21】:

                            我想,按照上面的“最佳算法使用 n+log n-2 比较”,我想出的不使用二叉树来存储值的代码如下:

                            在每次递归调用期间,数组大小减半。

                            所以比较的次数是:

                            第一次迭代:n/2 次比较

                            第二次迭代:n/4 次比较

                            第三次迭代:n/8 次比较

                            ... 最多记录 n 次迭代?

                            因此,总计 => n - 1 次比较?

                            function findSecondLargestInArray(array) {
                                let winner = [];
                                if (array.length === 2) {
                                    if (array[0] < array[1]) {
                                        return array[0];
                                    } else {
                                        return array[1];
                                    }
                                }
                                for (let i = 1; i <= Math.floor(array.length / 2); i++) {
                                    if (array[2 * i - 1] > array[2 * i - 2]) {
                                        winner.push(array[2 * i - 1]);
                                    } else {
                                        winner.push(array[2 * i - 2]);
                                    }
                                }
                                return findSecondLargestInArray(winner);
                            }
                            

                            假设数组包含 2^n 个数字。

                            如果有6个数字,那么3个数字会移动到下一级,这是不对的。

                            需要 8 个数字 => 4 个数字 => 2 个数字 => 1 个数字 => 2^n 个数字

                            【讨论】:

                              【解决方案22】:
                              package com.array.orderstatistics;
                              
                              import java.util.Arrays;
                              import java.util.Collections;
                              
                              public class SecondLargestElement {
                              
                                  /**
                                   *  Total Time Complexity will be n log n + O(1)
                                   * @param str
                                   */
                                  public static void main(String str[]) {
                                      Integer[] integerArr = new Integer[] { 5, 1, 2, 6, 4 };
                              
                              
                              
                                      // Step1 : Time Complexity will be n log(n)
                                      Arrays.sort(integerArr, Collections.reverseOrder());
                              
                                      // Step2 : Array.get Second largestElement
                                      int secondLargestElement = integerArr[1];
                              
                                      System.out.println(secondLargestElement);
                                  }
                              }
                              

                              【讨论】:

                              • 您忘记了计算比较次数的位。 (提示:在Arrays.sort() 的调用中隐藏了很多内容。
                              • 感谢 cmets。我现在已经更正了代码。最近的 JDK 中的 Arrays.sort(int[] a) 是使用 Dual-pivot Quicksort 算法实现的,该算法具有 O(n log n) 的平均复杂度并就地执行(例如,不需要额外的空间)。所以这个程序的总时间复杂度将是 O(n log n) + O(1)。
                              • 请为您的代码添加一些解释!当你这样做时,它会更容易理解。
                              【解决方案23】:

                              将数组按升序排序,然后将变量分配给第 (n-1) 项。

                              【讨论】:

                              • 效率很低。根据定义需要 n*log(n) 次比较。
                              • 使用蛮力或锦标赛方法,在蛮力中,第一次比较将采用 n-1 并在删除 largesT 时,第二次将采用 n-2 = n-1 + n-2 = 2n-3 比较与 O(1) 和 T(1)。对于锦标赛,您需要确保有 2 次方的元素,否则将额外的数字添加到数组中,比较将减少到 n + logn - 2(创建锦标赛的 logn 和 n-1 用于在锦标赛中输给最大的人)
                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2019-05-15
                              • 1970-01-01
                              • 1970-01-01
                              • 2017-01-17
                              • 1970-01-01
                              相关资源
                              最近更新 更多