【貪心】A_012 計算右側小於當前元素的個數(暴力 | 二分搜索)

一、題目描述

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].

Input: [5,2,6,1]
Output: [2,1,1,0] 
Explanation:
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.

二、題解

方法一:暴力(超時)

額…,

public List<Integer> countSmaller(int[] nums) {
    List<Integer> list = new LinkedList<>();
    for (int i = 0; i < nums.length; i++) {
        int count = 0;
        for (int j = i+1; j < nums.length; j++) {
            if (nums[j] < nums[i])
                count++;
        }
        list.add(count);
    }
    return list;
}

複雜度分析

  • 時間複雜度:O(n2)O(n^2)
  • 空間複雜度:O(n)O(n)

方法二:二分

可以想象一下有 5 個人的按升高升序排列隊伍進行報數,當報到 3 的時候,右邊很容易得到右 2 個人。如果隊伍無序則很麻煩。需要一個一個地向後數。

我們選擇從右往左查詢,每次查詢到 1 個數時,我們將其插入到 sorted_list 中,怎麼插入呢?我們選擇的位置是在 sorted_list 中找到一個小於 nums[i] 的最大元素,我們將 nums[i] 插入到該元素的後面。

這樣就能根據插入的位置判斷有多少個元素比自己小了,又因爲是從右往左枚舉的,所以插入的位置代表了右邊有多少個元素比自己小。

[1,3,6,1,2,3]

loop 3,  output: [3] -> 3 左邊有 0 個數,插在 0 位置
loop 2,  output: [2,3] -> 2 左邊有 0 個數,插在 0 位置
loop 1,  output: [1,2,3] -> 1 左邊有 0 個數,插在 0 位置
loop 6,  output: [1,2,3,6] -> 6 左邊有 3 個數,插在 3 位置
loop 3', output: [1,2,3',3,6] -> 3' 左邊有 2 個數,插在 2 位置
loop 1', output: [1',1,2,3',3,6] -> 1' 左邊有 0 個數,插在 0 位置
public List<Integer> countSmaller(int[] nums) {
    List<Integer> list = new ArrayList<>();
    Integer[] res = new Integer[nums.length];

    for (int i = nums.length-1; i >= 0; i--) {
        int l = 0, r = list.size();
        while (l < r) {
            int mid = (l + r) >>> 1;
            if (nums[i] > list.get(mid)) {
                l = mid + 1;
            } else {
                r = mid;
            }
        }
        res[i] = l;
        list.add(l, nums[i]);
    }
    return Arrays.asList(res);
}

複雜度分析

  • 時間複雜度:O(nlgn)O(nlgn)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章