web-dev-qa-db-ja.com

配列内の最初のn個の最大要素を見つける

一意の要素を含む配列があります。配列内の最初のn個の最大要素を可能な限り複雑さを抑えて見つける必要があります。これまで考えられた解決策は、O(n ^ 2)の複雑さを持っています。

    int A[]={1,2,3,8,7,5,3,4,6};
    int max=0;
    int i,j;
    int B[4]={0,0,0,0,};//where n=4;
     for(i=0;i<A.length();i++)
       {
         if(A[i]>max)
          max=A[i];
       }
     B[0]=max;
     for(i=1;i<n;i++){
       max=0;
       for(j=0;j<A.length();j++){
         if(A[j]>max&&A[j]<B[i-1])
            max=A[j];
       }
        B[i]=max;
     }

誰かがより複雑でないより良い解決策を思い付くことができれば、私は非常に感謝します。そして、元の配列を変更するつもりはありません!!

14
Poulami

選択アルゴリズム を使用して、k番目に大きい要素を見つけます。
次に、配列を反復処理して、それより大きい/等しいすべての要素を見つけます。

複雑さ:O(n)選択用、O(n)用反復するので、合計もO(n)です。

31
amit

n最大の要素を選択する通常のトリックは、最小優先度キューを維持することです。

  • 無条件にキューに挿入しますn最初の要素
  • 残りの各要素xについて、キューの最小要素よりも大きい場合はxを挿入し(O(log n)操作)、最小要素を削除します(O(log n))。
  • 完了すると、優先度キューにはn要素が含まれます。これは、元の配列のn最大要素です。

総複雑度:O(N log n)ここで、Nは配列内の要素の総数です。

実装の詳細は演習としてお任せします(最初のステップは、優先度付きキューについて学び、実装することです)。

11
Alexandre C.

要素が範囲内の整数(または任意の整数型)である場合、O(n)でこれを行うことができます。iからkまで、k> = iを含みます。この制約を使用して、適用できます。これに「バケットソート」。

アイデアは非常に単純です。 k-i +1バケットを割り当てます。次に、コレクションを繰り返し処理し、その整数のバケットをインクリメントします。次に、最後に、見つかった整数(つまり、バケット番号)をいくつでも作成することで、ソートされたリストを「再作成」できます。

例えば、

int collection[] = { 10, 4, 7, 1, 9, 0, 12 }; // maximum value to expect is 12, minimum is 0
int buckets[ 13 ] = { 0 };

for( int i = 0; i < 13; i++ )
{
      int n = collection[ i ];
      buckets[ n ]++;
}


// the first n largest elements (n = 4)

for( int j = 12; j >= 12 - 4; j-- )
{
      int n = buckets[ j ];

      while( n > 0 )
      {
           printf( "%d ", j );
           n--;
      }
}
printf( "\n" ); 
2
Man Vs Code

これを解決するには、ヒープ(maxHeap)を使用した優先度付きキューを使用できます。ヒープをn回実行して、最初のn個の最大要素を取得します。各ヒープ操作にはO(log N)時間がかかるため、N個のヒープ操作はO(N log N)時間になります。

1
harunrashid

クイックソートの修正バージョンを使用します。配列全体を実際にソートする必要はありません。ピボット値よりも大きいN個の要素を分割するだけで済みます。詳細については、「アルゴリズムの概要」を参照してください。

1
Nam Nguyen

私はこれを信じていませんが、O(n)でそれからヒープを作成することもできます。次に、ルートkをk回削除し、最大k個のヒープをヒープ化します。このように、最大​​数ごとにlog(n)のコストがかかります。

public class HeapSort1{                                                          
    public static void main(String args[]){                                  
            int[] array={5,75,1,5,4,1,2,4,8,4,2,15,4,2,1,5,779,9,1};         
            int heapsize=array.length-1;                                     
            for(int i=heapsize/2;i>=0;i--){                                  
                    maxHeapify(array,i,heapsize);                            
            }                                                                
            for(int i=heapsize;i>0;i--){                                     
                    array[i]=array[0]+array[i];                              
                    array[0]=array[i]-array[0];                              
                    array[i]=array[i]-array[0];                              
                    maxHeapify(array,0,--heapsize);                          
            }                                                                
            printArray(array);                                               
    }                                                                        
    public static void maxHeapify(int[] array,int i,int heapsize){           
            int largest=i;                                                   
            int left=2*i+1;                                                  
            int right=2*i+2;                                                 
            if(left<=heapsize && array[left]>array[i]){                      
                    largest=left;                                            
            }                                                                
            if(right<=heapsize && array[right]>array[largest]){              
                    largest=right;                                           
            }                                                                
            if(largest!=i){                                                  
                    array[i]=array[largest]+array[i];                        
                    array[largest]=array[i]-array[largest];                  
                    array[i]=array[i]-array[largest];                        
                    maxHeapify(array,largest,heapsize);                      
            }                                                                
    }                                                                        
    public static void printArray(int[] array){                              
            System.out.print("\n [");                                        
            for(int i=0;i<array.length;i++){                                 
                    System.out.print(array[i]+" ");                          
            }                                                                
            System.out.print("] \n");                                        
    }  
    public static int getMax(){
            int max=array[0];
            array[0]=array[heapsize];
            maxHeapify(array,0,--heapsize);
    }

 }                                                                                                                                                             
0
Yashdeep Hinge

@AlexandreCに従ってこれを試しました。

これにより、無制限の入力の上位10項目が取得されます。入力から20項目を処理した後に壊れます。

import random
import time
top_10_items = []
cnt = 1
while True:
    Rand = random.randint(1,100)
    print(Rand)

    time.sleep(1)
    if len(top_10_items) !=10:
        top_10_items.append(Rand)
    else:
        m = min(top_10_items)
        if Rand > m:
            top_10_items.append(Rand)
            top_10_items.remove(m)

    print(top_10_items)

    cnt+=1
    if cnt==20:
        break
0
user1050619