【问题标题】:How to find the number of elements in the array that are bigger than all elements after it?如何找到数组中大于其后所有元素的元素数?
【发布时间】:2015-03-03 18:08:42
【问题描述】:

我有一个函数,它接受一个由 N 个正整数组成的一维数组并返回大于下一个的元素的数量。问题是存在一个功能可以在更好的时间做到这一点吗?我的代码如下:

int count(int *p, int n) {
    int i, j;
    int countNo = 0;
    int flag = 0;
    for(i = 0; i < n; i++) {
        flag = 1;
        for(j = i + 1; j < n; j++) {
            if(p[i] <= p[j]) {
                flag = 0;
                break;
            }
        }
        if(flag) {
            countNo++;
        }
    }
    return countNo;
}

我的解决方案是O(n^2)。能不能做得更好?

【问题讨论】:

    标签: c algorithm


    【解决方案1】:

    你可以在线性时间内解决这个问题(O(n) time)。请注意,数组中的最后一个数字将始终是符合问题定义的有效数字。所以该函数将始终输出一个大于等于 1 的值。

    要使数组中的任何其他数字成为有效数字,它必须大于或等于数组中该数字之后的最大数字。

    所以从右到左遍历数组,跟踪到目前为止找到的最大数字,如果当前数字大于或等于到目前为止找到的最大数字,则增加计数器。

    Working code

    int count2(int *p, int n) {
        int max = -1000;  //this variable represents negative infinity. 
        int cnt = 0;
        int i;
        for(i = n-1; i >=0; i--) {
            if(p[i] >= max){
                cnt++;
            }
            if(p[i] > max){
                max = p[i];
            }
        }
        return cnt;
    }
    

    时间复杂度:O(n)
    空间复杂度:O(1)

    【讨论】:

      【解决方案2】:

      可以在O(n)完成。

      int count(int *p, int n) {
          int i, currentMax;
          int countNo = 0;
          currentMax = p[n-1];   
          for(i = n-1; i >= 0; i--) {
      
           if(currentMax < p[i])
           {
              countNo ++;
              currentMax = p[i];
           }
          }
          return countNo;
      }
      

      【讨论】:

        【解决方案3】:

        创建辅助阵列aux:

        aux[i] = max{arr[i+1], ... ,arr[n-1] } 
        

        可以通过从右到左扫描数组在线性时间内完成。

        现在,您只需要 arr[i] &gt; aux[i] 等元素的数量

        这是在O(n) 中完成的。

        【讨论】:

        • 你甚至不需要辅助数组,是吗?
        • @MOehm 不,但我发现以这种方式建模更容易。很明显,您正在寻找的正是这种方式(一个像arr[i] &gt; max{arr[i+1], ..., arr[n-1] } 这样的元素)。如果以后的空间成为问题,则很容易对其进行优化。
        【解决方案4】:

        在数组中向后走,并跟踪当前的最大值。每当您找到一个新的最大值时,该元素都会比后面的元素大。

        【讨论】:

          【解决方案5】:

          是的,可以在O(N) 时间完成。我会给你一个关于如何去做的方法。如果我正确理解您的问题,您希望元素的数量大于数组中接下来的所有元素,前提是保持顺序。

          所以:

          Let len = length of array x
          
          {...,x[i],x[i+1]...x[len-1]}
          
          We want the count of all elements x[i] such that x[i]> x[i+1] 
          and so on till x[len-1]
          

          从末尾开始遍历数组,即i = len -1,并跟踪您遇到的最大元素。

          可能是这样的:

          max = x[len-1] //A sentinel max
          
          //Start a loop from i = len-1 to i = 0;
          
          if(x[i] > max)
            max = x[i] //Update max as you encounter elements
          
          //Now consider a situation when we are in the middle of the array at some i = j
          
          {...,x[j],....x[len-1]}
          
          //Right now we have a value of max which is the largest of elements from i=j+1 to len-1
          

          因此,当您遇到大于maxx[j] 时,您基本上发现了一个大于接下来所有元素的元素。你可以有一个计数器并在发生这种情况时增加它。

          显示算法流程的伪代码:

           counter = 0
           i = length of array x - 1
           max = x[i]
           i = i-1
           while(i>=0){
                if(x[i] > max){
                   max = x[i]   //update max
                   counter++    //update counter
                } 
                i--
           }
          

          所以最终counter 将拥有您需要的元素数量。

          希望我能够向您解释如何解决这个问题。作为起点,编写代码应该是一个有趣的练习。

          【讨论】:

            猜你喜欢
            • 2015-08-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-24
            • 2021-06-07
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多