1. 程式人生 > 實用技巧 >LeetCode 1365 有多少小於當前數字的數

LeetCode 1365 有多少小於當前數字的數

LeetCode 1365 有多少小於當前數字的數

https://leetcode-cn.com/problems/how-many-numbers-are-smaller-than-the-current-number/

暴力列舉

因為資料量並不大,即使是複雜度高的暴力列舉也應該能通過。所以先把暴力列舉法安排上。

class Solution {
public:
    // time and space complexity : O(N^2), O(1)
    vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
        int sz = nums.size();
        vector<int> ans(sz, 0);

        for (int i = 0; i < sz; ++i) {
            int cnt = 0;
            for (int j = 0; j < sz; ++j) {
                if (nums[j] < nums[i]) 
                    ++cnt;
            }
            ans[i] = cnt;
        }

        return ans;
    }
};

快速排序

如果我們把陣列排序,那麼對於排序後陣列的某一個數而言,它前面有多少個數就說明有多少個數小於它。而該數前面有多少個數又反應在它的下標之中。但是,這裡需要注意兩個問題:
(1)排序後原陣列的順序就變了,所以需要原陣列中的下標;
(2)如果陣列中有相同元素,那麼它們在排序之後會排在一起,它們的下標彼此不同但是陣列中小於它的數數量卻是相同的,這種情況需要做特殊處理。

struct MyCompare {
    bool operator()(const pair<int, int>& a, const pair<int, int>& b) {
        return a.first < b.first;
    }
} cmp;

class Solution {
public:
    // time and space complexity : O(NlogN), O(N)
    vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
        int sz = nums.size();
        vector<pair<int, int>> arr;
        for (int i = 0; i < sz; ++i) {
            arr.push_back(make_pair(nums[i], i));
        }

        vector<int> ans(sz, 0);
        sort(arr.begin(), arr.end(), cmp);
        int prev = -1;
        for (int i = 0; i < sz; ++i) {
            int idx = arr[i].second;
            if (prev == -1 || arr[i].first != arr[i - 1].first) {
                prev = i;
            }
            // 如果arr[i]和arr[i - 1]是相同的,則prev的值仍維持不變
            ans[idx] = prev;
        }

        return ans;
    }
};

計數排序

既然快速排序能夠達到解題的目的,那麼其他的排序方式同樣也可以。注意到題目限定陣列中每個元素的範圍在0和100之間,這個範圍不大,這提示我們可以使用計數排序。和上面的快排方法類似,只不過排序方法變成了計數排序。程式碼略。