leetcode 面試題51. 數組中的逆序對(超時ing)

在數組中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。

示例 1:

輸入: [7,5,6,4]
輸出: 5

限制:

0 <= 數組長度 <= 50000

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。


思路分析

最開始思路是動態規劃,但是理所應當的超時了,代碼如下:

class Solution {
public:
    int reversePairs(vector<int>& nums) {
        if(nums.size() <= 0)
            return 0;
        vector<int> dp(nums.size() + 1,0);//dp[i]表示從i開始到末尾的最大逆序對數目
        dp[nums.size() - 1] = 0;
        for(int i = nums.size() - 1;i >= 0;--i){
            for(int j = i + 1;j < nums.size();++j){
                if(nums[i] > nums[j]){
                    dp[i] = max(dp[i],dp[j]) + 1;
                }
                else
                    dp[i] = max(dp[i],dp[j]);
            }
        }
        return dp[0];
    }
};

在這裏插入圖片描述

第二種思路,歸併算法,很遺憾,還是超時。。。
雖然超時,但是這裏記錄一下爲什麼會想到歸併呢:
看下流程:
在這裏插入圖片描述
第一步,將左邊的10填入數組:
在這裏插入圖片描述

第二步,將右邊的12填入數組,並且此時在左邊區域的所有數值都比12大,那麼此時逆序對數目加(mid - i + 1)
在這裏插入圖片描述
第三步,將左邊14放入數組
在這裏插入圖片描述
第四步,將21放入數組,同理,計算左邊區域個數
在這裏插入圖片描述
後續進行同樣的操作,最後結果是:
在這裏插入圖片描述
這就是大致思路

class Solution {
    int merge(vector<int>& nums, vector<int> temp, int left, int right){
        if(left >= right)
            return 0;
        int mid = left + (right - left) / 2;
        int count = merge(nums,temp,left,mid) + merge(nums,temp,mid + 1,right);//右區間
        for(int i = left;i <= right;++i)
            temp[i] = nums[i];
        int i = left,j = mid + 1;
        for(int k = left;k <= right;++k){
            if(i == mid + 1){
                nums[k] = temp[j];
                ++j;
            }
            else if(j == right + 1){
                nums[k] = temp[i];
                ++i;
            }
            else if(temp[i] <= temp[j]){
                nums[k] = temp[i];
                ++i;
            }
            else{
                nums[k] = temp[j];
                ++j;
                count += (mid - i + 1);
            }
        }
        return count;
    }
public:
    int reversePairs(vector<int>& nums) {
        vector<int> temp(nums.size());
        return merge(nums, temp, 0,nums.size() - 1);
    }
};

值得幸運的是,在討論區看見同校北郵師兄的優化方案,藉以解決,他的代碼優化如下:
計組upper_bound()函數,簡化了歸併的那一步操作。
後附上師兄leetcode主頁鏈接:https://leetcode-cn.com/u/mike-meng/,全站排名19的大佬哦!

class Solution {
public:
    int dfs(vector<int> & nums,int l,int r){
        if(r-l <= 1) return 0;
        int mid = (l+r)>>1;
        int res = dfs(nums,l,mid) + dfs(nums,mid,r);
        sort(nums.begin()+l,nums.begin()+mid);
        for(int i = mid; i < r; ++i)
            res += nums.begin() + mid - upper_bound(nums.begin()+l,nums.begin()+mid,nums[i]);
        return res;
    }
    int reversePairs(vector<int>& nums) {
        return dfs(nums,0,nums.size());
    }
};

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章