315. Count of Smaller Numbers After Self

time: O(nlogn)

space: O(n)

้€™้กŒ่ช็œŸๅŽป็œ‹ๅฏไปฅ็™ผ็พ, ๅ…ถๅฏฆไธป้ซ”ๅฐฑๆ˜ฏ mergeSort, ไฝ†็‚บไป€้บผๅฏไปฅๅœจ mergeSort ็š„้Ž็จ‹ไธญ

้”ๆˆ count ๅณ้‚Šๆฏ”ๆœฌ่บซๅฐ็š„็ตๆžœๅ‘ข๏ผŸ

ไธป่ฆๆ˜ฏ่ฆๅ…ˆๅˆฉ็”จไธ€ๅ€‹ Item class, ไพ†่จ˜้Œ„ๅŽŸๆœฌ็š„ๅ€ผๅ’Œ index

้‚„ๆœ‰ๅˆฉ็”จไธ€ๅ€‹ count ้™ฃๅˆ—, ไพ†่จ˜้Œ„ๆœ€ๅพŒ็š„็ญ”ๆกˆ, ๆ€Ž้บผ็ด€้Œ„็ญ”ๆกˆๅ‘ข๏ผŸ

ๅฐฑๆ˜ฏๅˆฉ็”จ Item class ่ฃก้ขๅŽŸๆœฌ็š„ๅ€ผๅ’Œ index

็•ถ็ฌฌไธ€ๅ€‹ while ๆ™‚, ๅฆ‚ๆžœ

merge 5, 2

1.

if (items[l].val > items[r].val) =>

a. ไปฃ่กจ็›ฎๅ‰ๆ˜ฏ้€†ๅบ(ๅทฆ้‚Š ๅคงๆ–ผ ๅณ้‚Š), ๆ‰€ไปฅ่ฆ ๅณ้‚Š ่ฆ็งปๅˆฐ ๅทฆ้‚Š, ๆ‰ๆœƒๆ˜ฏ sorted, ไปฅ้€™ไพ†่ชชๅฐฑๆ˜ฏ item[r++] ๅŠ ๅˆฐ temp

b. ไฝ†้€†ๅบไนŸไปฃ่กจไบ†ไธ€ไปถไบ‹ => ๅณ้‚Šๆœ‰ไธ€ๅ€‹ๆ•ธๅคงๆ–ผๅทฆ้‚Š, ๆ‰€ไปฅ rightCount++

else ไนŸๅฐฑๆ˜ฏ sorted, ้‚ฃ่ฆๅšไป€้บผๅ‘ข๏ผŸ ๅฐฑๆ˜ฏ่ฆ่จ˜้Œ„็ตๆžœๅˆฐ count[] ้™ฃๅˆ—, ๅ› ็‚บๅทฒ็ถ“ๆฒ’ๆœ‰ๅณ้‚Šๆฏ”ๅทฆ้‚Šๅคง็š„ case ไบ†

a. ่จ˜้Œ„็ตๆžœๅˆฐ count[] ้™ฃๅˆ— .=> ้€™ๅฐฑ่ฆๅˆฉ็”จๅˆฐ items[l].idx ไบ† so count[items[l.idx]] += rightCount

b. ๆŠŠ l ็›ฎๅ‰ๅ…งๅฎนๅŠ ๅ…ฅ, item[l++] ๅŠ ๅˆฐ temp

ex 5, 2 .=> 2, 5 ., rightCount++, ๅกžไบ† 2 ๅˆฐ temp[0]

        while (l <= mid && r <= right) {
            if (items[l].val > items[r].val) { 
            // l > r, means move r to l, so insert r data to temp, 
            // and add rightcount , ex 5 2 => 2 5, but rightCount should++
                rightCount++;
                temp[tempIdx++] = items[r++];
            } else { 
            // if l < r, it is sorted, ex: 2 5, 
            // cal count result(count[l index] += rightCnt), 
            // insert l data to temp
                count[items[l].idx] += rightCount;
                temp[tempIdx++] = items[l++];
            }
   
        }

็ฌฌไบŒๅ€‹ while ๅฐฑ่ทŸ ็ฌฌไธ€ๅ€‹ while else ๅ…ถๅฏฆๅ…งๅฎนไธ€ๆจฃ ๏ผˆ ๅ› ็‚บๆ˜ฏ l <= mid)

while (l <= mid) { // insert remained l data, and cal count, (insert l data means cal result!)
            count[items[l].idx] += rightCount;
            temp[tempIdx++] = items[l++];
        }

ex 5 2 .=> 2, 5 ไน‹ๅพŒ, ้‚„ๅ‰ฉไธ‹ 5, ๆ‰€ไปฅๅกž 5 ๅˆฐ temp[1] .( while l <= mid

5 ็š„ count+= rightCount, ไนŸๅฐฑๆ˜ฏ count[0] += 1

ๆŽฅ่‘—ๆ˜ฏ merge 1, and merge 2,5

ex 2 .5 merge 1 ๆ™‚ =>

lowPtr . | hiPtr

2 . 5 . 1

=> ็ถ“ๆญทไน‹ๅ‰็ฌฌไธ€ๅ€‹ while ๅพŒ => 1 2 5 .=> rightCount = 1

lowPtr . mid hiPtr

2 . 5 . 1

while (l <= mid ) .=> ๆ‰€ไปฅ 2, 5 (count[1], count[0])้ƒฝ่ฆ += rightCount (ๅ› ็‚บๆœ‰ๅ€‹ๅฐ็š„1 ๅˆฐๅทฆ้‚Šๅ•ฆ

        while (l <= mid) { // insert remained l data, and cal count, (insert l data means cal result!)
            count[items[l].idx] += rightCount;
            temp[tempIdx++] = items[l++];
        }

        while (r <= right) { // insert remained r data
            temp[tempIdx++] = items[r++];
        }

        // finally put sorted temp data to items
        for (int p = 0; p < temp.length; p++) {
            items[left + p] = temp[p];
        }

ๆœ€ๅพŒๆŠŠ temp ็ตๆžœ(sort ็š„๏ผ‰, ๆ›ดๆ–ฐๅˆฐๅŽŸๆœฌ items ไธญ

class Solution {
    private class Item { 
        int val;
        int idx;

        public Item(int val, int idx) {
            this.val = val;
            this.idx = idx; // for count use
        }
    }

    public List<Integer> countSmaller(int[] nums) {

        int n = nums.length;
        int[] count = new int[n];
        Item[] items = new Item[n];

        for (int i = 0; i < n; i++) {
            items[i] = new Item(nums[i], i);
        }

        mergeSort(items, 0, n - 1, count);

        List<Integer> result = new ArrayList<>();
        for (int cnt : count) {
            result.add(cnt);
        }

        return result;

    }

    private void mergeSort(Item[] items, int left, int right, int[] count) {

        if (left >= right) return;

        int mid = (right + left) >> 1;
        mergeSort(items, left, mid, count);
        mergeSort(items, mid + 1, right, count);
        merge(items, left, mid, right, count);

    }

    private void merge(Item[] items, int left, int mid, int right, int[] count) {

        Item[] temp = new Item[right - left + 1];
        int tempIdx = 0;

        int l = left;
        int r = mid + 1;
        int rightCount = 0;

        while (l <= mid && r <= right) {
            if (items[l].val > items[r].val) { 
            // l > r, means move r to l, so insert r data to temp, 
            // and add rightcount , ex 5 2 => 2 5, but rightCount should++
                rightCount++;
                temp[tempIdx++] = items[r++];
            } else { 
            // if l < r, it is sorted, ex: 2 5, 
            // cal count result(count[l index] += rightCnt), 
            // insert l data to temp
                count[items[l].idx] += rightCount;
                temp[tempIdx++] = items[l++];
            }
        }

        while (l <= mid) { // insert remained l data, and cal count, (insert l data means cal result!)
            count[items[l].idx] += rightCount;
            temp[tempIdx++] = items[l++];
        }

        while (r <= right) { // insert remained r data
            temp[tempIdx++] = items[r++];
        }

        // finally put sorted temp data to items
        for (int p = 0; p < temp.length; p++) {
            items[left + p] = temp[p];
        }
    }
}

Last updated