315. Count of Smaller Numbers After Self

来源:互联网 发布:java区块链开源项目 编辑:程序博客网 时间:2024/05/17 17:17

You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].

Example:

Given nums = [5, 2, 6, 1]To the right of 5 there are 2 smaller elements (2 and 1).To the right of 2 there is only 1 smaller element (1).To the right of 6 there is 1 smaller element (1).To the right of 1 there is 0 smaller element.

Return the array [2, 1, 1, 0].


题目大意:

找出每个元素的逆序对数。

1.自己做的第一反应就是暴力  循环两次找每个元素比其小的个数  O(n^2)   of course 是超时了

class Solution {public:    vector<int> countSmaller(vector<int>& nums) {        int len = nums.size();        vector<int>dp(len,0);        for(int i = len-1; i>= 0; i--){            int ans = 0;            for(int k = len-1; k > i; k--){                if(nums[i] > nums[k])                    ans++;            }            dp[i] = ans;        }        return dp;    }};



2.标准方法,mergesort 

归并排序,并在归并的时候数清楚每个元素对应的逆序对数

这里用unordered_multimap是用来解决给出的case里有重复的值,因为归并是稳定的,所以map里存的时候既要能存重复的,又要按照原始顺序存入

该代码在leetcode上AC了。

但是有个奇怪的现象,就是对于case:

5,2,6,1,4,3,7,8,9,2

leetcode上运行结果是:

5 1 4 0 2 1 1 1 1 0

而我的xcode上出来的结果是:

5 0 4 0 2 1 1 1 1 1 

问题就在于:

合并的时候,是判断 哪个在前面的时候有问题,即   if(nums[i] < nums[j])

即用该语句得到的结果刚好在两个编辑器上得到的结果相反。。。我也不知道为什么。。。 

class Solution {public:    void mergesort(vector<int>& nums,vector<int>& count, int left, int mid, int right){        int n = right - left + 1;        vector<int>number(n,0);        vector<int>cou(n,0);        int j = right;        int i = mid;        while(i >= left && j >= mid){            if(nums[j] < nums[i]){                count[i] += (j - mid);                --i;            }else{                --j;            }        }        i = left, j = mid + 1;        int k = 0;        while(i <= mid && j <= right){            if(nums[i] < nums[j]){                number[k] = nums[i];                cou[k] = count[i];                ++k;                ++i;            }else{                number[k] = nums[j];                cou[k] = count[j];                ++k;                ++j;            }        }        while(i <= mid){            number[k] = nums[i];            cou[k] = count[i];            ++k;            ++i;        }        while(j <= right){            number[k] = nums[j];            cou[k] = count[j];            ++k;            ++j;        }        for(int k = 0; k < n; k++){            nums[k+left] = number[k];            count[k+left] = cou[k];        }    }        void merge(vector<int>& nums,vector<int>& count, int i, int j){        if(i < j){            int mid = i + (j - i)/2;            merge(nums, count, i, mid);            merge(nums, count, mid+1, j);            mergesort(nums, count, i, mid, j);        }    }        vector<int> countSmaller(vector<int>& nums) {        int n = nums.size();        vector<int> count(n,0);        unordered_multimap<int,int>mp;        unordered_multimap<int, int>::iterator it;        vector<int>res(n,0);        for(int i = 0; i < n; i++){            mp.insert({nums[i],i});        }        vector<int>number(nums.begin(), nums.end());        merge(nums,count,0,n-1);        for(int j = 0; j < n; j++){            it = mp.find(nums[j]);            res[it->second] = count[j];            mp.erase(it);        }        return res;    }};

当然还有很多很好的思路和代码,等到二刷的时候再补上

0 0