(アルゴリズム) マージソートの拡張、小和問題、逆順問題。(乳母レベルの超詳細解説)

少額問題

  • 簡単な説明

 配列があり、左から右にトラバースし、ビットに移動するたびに、それよりも小さいすべての数字を左に追加し、最終的な合計を小計として記録します。以下は、一般的な実践プロセスの例です。

したがって、私たちが必要としているのは、より迅速なアプローチです。

  •  分析ロジック

以前のマージソートを引き続き使用して、マージ部分を変更できます。

以下を例に取りますが、それでも配列を 2 つに分割します

図1

図2 

それでも2つの指標を準備し、空のリストが役立ちます

左側の 1 を見て、3 の左側の p1 が 1 を指し、右側の p2 が 3 を指す、比較、1<3、小計に 1 を追加、ヘルプ リストに 1 を格納、インジケータ p1 を右に移動範囲外 (左側に数字がない) を選択し、右側の 3 を直接コピーします。ヘルプ リストを入力し、ヘルプ リストを配列にコピーします。(ヘルプ[1,3])

上位層に入り、p1 は 1 を指し、p2 は 2 を指し、1<2、小和に 1 を加算、ヘルプ リストに 1 を格納、p1 は 3 を指し、3>2、小和に 0 を加算、格納2 ヘルプ リストの右側に数字がありません。左側の残りを直接ヘルプ リストにコピーします (help[1, 2, 3])。

(5、6は同じ)

上層に入り、この時点で左右がソートされ、p1が1を指し、p2が5を指し、5>1、(右側も順番なので、5以降の数字はすべて1より大きい) 、次に直接進みます 下付き文字を計算するだけです) 1*2 を小さな和に追加し、ヘルプ リストに 1 を格納します。など、そして最後に配列全体に順序があり、配列の最小合計を見つけます。

(ps: 1. 左側の数値が右側の数値よりも大きい場合、右側の数値をヘルプ リストに保存すると、p2 インジケーターが 1 ビット右に移動します。つまり、小さい方が移動します。ヘルプに入ります; 2. 合計が計算されるたびにソートされるため、ソートは結果に影響しません)

  •  コード (Java):
 public static int process(int[] arr,int L,int R){
  if(L==R){
    return;
  }
  int M = L+((R-L)>>1);
  merge(arr,L,M,R);
  return process(arr,L,M)+process(arr,M+1,R)+merge(arr, L,M,R);
}  

public static int merge(int[] arr,int L,int R){
  int p1 = L;
  int p2 = M+1;
  int[] help = new int[R-L+1];
  int res =0;    //小和
  int i = 0;
  while(p1 <= M && p2 <= R){
    res += arr[p1] < arr[p2] ? (R - p2+1)*arr[p1]:0;    //左边小则该数乘右边下标数记小和
    help[i] = arr[p1] < arr[p2] ? arr[p1++]:arr[p2++];
  while(p1 <= M){
    help[i++] = arr[p1++]; 
  }
  while(p2 <= R){
    help[i++] = arr[p2++];
  }
  for(int i = 0,i < help.length,i++){
    arr[L+i] = help[i];    //把排好序的help拷贝到该次求小和数组范围
  return res;
  }
  }  
}

 逆ペア問題

  • 簡単な説明

配列, 左の数が右の数よりも大きい場合, 逆順のペアとして記録されます. その本質は前の小和問題と同じです. また、マージを変更するだけで済みます. (小さな和を見つけることは、左辺が右辺よりも小さいことを見つけることです)

 上記は、配列内のすべての逆のペアです。

Supongo que te gusta

Origin blog.csdn.net/qq_48860282/article/details/123939514
Recomendado
Clasificación