LeetCode 315 Count of Smaller Numbers After Self(树状数组)

来源:互联网 发布:破解app软件网站 编辑:程序博客网 时间:2024/06/05 03:35

You are given an integer array nums and you have to return a newcounts array.The counts array has the property where counts[i] is the number of smaller elements to the right ofnums[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].

Subscribe to see which companies asked this question


题目链接:https://leetcode.com/problems/count-of-smaller-numbers-after-self/


题目分析:其实就是求逆序数,可以用树状数组或归并排序实现,这里用的树状数组(感觉比归并好些的多。。。)

这是一开始写的,老老实实中规中矩的排序离散化,跑了26ms

public class Solution {        class Data implements Comparable {        int val, pos;                public Data(int val, int pos) {            this.val = val;            this.pos = pos;        }                @Override          public int compareTo(Object o) {              Data data = (Data) o;              if (this.val >= data.val) {                  return 1;              }              else {                return -1;            }        }    }        public int lowbit(int x) {        return x & (-x);    }        public void add(int x, int len, int[] cnt) {        for (int i = x; i <= len; i += lowbit(i)) {            cnt[i] ++;        }     }        public int getCnt(int x, int[] cnt) {        int ans = 0;        for (int i = x; i > 0; i -= lowbit(i)) {            ans += cnt[i];        }        return ans;    }        public List<Integer> countSmaller(int[] nums) {        List<Integer> ans = new ArrayList<>();        int len = nums.length;        if (len == 0) {            return ans;        }        Data[] d = new Data[len];        int[] cnt = new int[len + 1];        int[] nums2 = new int[len + 1];        int[] rev = new int[len];        for (int i = 0; i < len; i ++) {            d[i] = new Data(nums[i], i + 1);        }        Arrays.sort(d);        nums2[d[0].pos] = 1;        int id = 1;        for(int i = 1; i < len; i ++) {            if (d[i].val == d[i - 1].val) {                nums2[d[i].pos] = id;            }            else {                nums2[d[i].pos] = ++ id;            }        }        int revCnt = 0;        for (int i = len; i >= 1; i --) {            add(nums2[i], len, cnt);            rev[revCnt ++] = getCnt(nums2[i] - 1, cnt);        }        for (int i = revCnt - 1; i >= 0; i --) {            ans.add(rev[i]);        }        return ans;    }}

看了discuss里的一种离散化方法,瞬间8ms,不过那种离散化方法只适用于负数不太小,正数不太大的情况

public class Solution {    public int lowbit(int x) {        return x & (-x);    }        public void add(int x, int len, int[] cnt) {        for (int i = x; i <= len; i += lowbit(i)) {            cnt[i] ++;        }     }        public int getCnt(int x, int[] cnt) {        int ans = 0;        for (int i = x; i > 0; i -= lowbit(i)) {            ans += cnt[i];        }        return ans;    }        public List<Integer> countSmaller(int[] nums) {        List<Integer> ans = new ArrayList<>();        int len = nums.length;        if (len == 0) {            return ans;        }        int[] nums2 = new int[len + 1];        int[] rev = new int[len];        int mi = Integer.MAX_VALUE;        int ma = Integer.MIN_VALUE;        for (int i = 0; i < len; i ++) {            mi = Math.min(nums[i], mi);        }        for (int i = 1; i <= len; i ++) {            nums2[i] = nums[i - 1] - mi + 1;            ma = Math.max(ma, nums2[i]);        }        int[] cnt = new int[ma + 1];        int revCnt = 0;        for (int i = len; i >= 1; i --) {            add(nums2[i], ma, cnt);            rev[revCnt ++] = getCnt(nums2[i] - 1, cnt);        }        for (int i = revCnt - 1; i >= 0; i --) {            ans.add(rev[i]);        }        return ans;    }}


0 0
原创粉丝点击