Sword はオファーを参照します (C++)-JZ51: 配列内の逆順ペア (アルゴリズム - ソート)

著者: Zhai Tianbao Steven
著作権表示: 著作権は著者に属します。商業的転載の場合は、許可について著者に連絡してください。非商業的な転載の場合は、出典を示してください。

タイトル説明:

配列内の 2 つの数値。前の数値が次の数値より大きい場合、2 つの数値は逆ペアを形成します。配列を入力し、この配列内の逆ペアの合計数 P を求めます。そして、P モジュロ 1000000007 の結果を出力します。つまり、出力 P mod 1000000007
データ範囲: データの 50% の場合、サイズ ≤ 104
データの 100% の場合、サイズ ≤ 105

配列内のすべての数値の値は 0≤val≤109 を満たします

要件: 空間計算量 O(n)、時間計算量 O(nlogn)

例:

入力:

[1,2,3,4,5,6,7,0]

戻り値:

7

問題解決のアイデア:

この問題に対する従来の解決法は暴力的な方法ですが、この問題は nlogn の複雑さを必要とするため、マージ ソートによって解決できます。

  1. 普通にマージソートを書きます。
  2. 結合ソートのマージおよびソートのプロセスでは、2 つの部分間隔のデータが順番に比較され、新しい順序が再構築されます。このとき、左側の値 A が右側の値 B より大きい場合、 A から中間位置 C に直接データ数を転送できます。部分間隔がソートされているため、A が B より大きいため、A と C の間のすべてのデータも B より大きくなければならず、逆順序のペアを形成できます。
  3. このようにして、時間計算量はトピックの要件を満たします。

テストコード:

class Solution {
public:
    int mod = 1000000007;
    // 归并排序
    int mergeSort(vector<int>& data, int left, int right){
        // 停止
        if(left >= right)
            return 0;
        // 中间位
        int mid = (left + right) / 2;
        // 拆分合并,累加逆序对数量
        int count = mergeSort(data, left, mid) + mergeSort(data, mid + 1, right);
        count %= mod;
        // 排序
        int i = left, j = mid + 1;
        vector<int> temp(data);
        for(int t = left; t <= right; ++t){
            // i如果到了mid+1,说明左子区间遍历完毕,后续直接取右区间数据即可
            if(i == mid + 1){
                data[t] = temp[j];
                j++;
            }
            // j如果到了right+1,说明右子区间遍历完毕,后续直接取左区间数据即可
            // 如果左侧值小于右侧值,不符合逆序对,正常排序即可
            else if(j == right + 1 || temp[i] <= temp[j]){
                data[t] = temp[i];
                i++;
            }
            // 如果左侧值大于右侧值,说明左侧当前位置到左子区间结束的数值,都大于该右侧值,直接计算数量:mid-i+1;然后正常排序
            // 这样操作降低了时间复杂度
            else{
                data[t] = temp[j];
                j++;
                count += mid - i + 1;
            }
        }
        return count % mod;
    }
    // 逆序对
    int InversePairs(vector<int>& nums) {
        int size = static_cast<int>(nums.size());
        int count = mergeSort(nums, 0, size - 1);
        return count;
    }
};

おすすめ

転載: blog.csdn.net/zhaitianbao/article/details/131371768