Count of Smaller Number before itself.

Give you an integer array (index from 0 to n-1, where n is the size of this array, data value from 0 to 10000) . For each element Ai in the array, count the number of element before this element Ai is smaller than it and return count number array.

Example

Example 1:

Input:
[1,2,7,8,5]
Output:
[0,1,2,3,2]

Example 2:

Input:
[7,8,2,1,3]
Output:
[0,1,0,0,2]

Clarification

Before you do this, we suggest you complete the following three questions: Segment Tree Build, Segment Tree Query II,and Count of Smaller Number before itself I 。

思路:用segment tree来记录当前点之前的所有的count,并且维护线段树的count,首先建立一个空的线段树,然后每次遇见一个数,把他的index node count值++,最后 querySum (0, A[i]-1)的线段count即可,注意一定要做一个特殊例子判断,就是A[i] == 0,比0小的数没有,因为数组是[0,10000] 的数,所以,没有,list直接加0,但是0这个node的count还是要++,因为他是其他比0大的数的小于的count;

public class Solution {
    /**
     * @param A: an integer array
     * @return: A list of integers includes the index of the first number and the index of the last number
     */
    public List<Integer> countOfSmallerNumberII(int[] A) {
        List<Integer> list = new ArrayList<>();
        SegmentTree segmentTree = new SegmentTree(10001);
        for(int num: A) {
            if(num == 0) {
                list.add(0);
            } else {
                list.add(segmentTree.querySum(0, num - 1));
            }
            segmentTree.add(num, 1);
        }
        return list;
    }

    public class SegmentTreeNode {
        public int start, end;
        public int sum;
        public SegmentTreeNode left, right;
        public SegmentTreeNode (int start, int end) {
            this.start = start;
            this.end = end;
            this.sum = 0;
            this.left = null;
            this.right = null;
        }
    }

    public class SegmentTree {
        public SegmentTreeNode root;
        public int size;
        public SegmentTree (int size) {
            this.size = size;
            this.root = buildTree(0, size - 1);
        }

        public SegmentTreeNode buildTree(int start, int end) {
            if(start > end) {
                return null;
            }
            SegmentTreeNode node = new SegmentTreeNode(start, end);
            if(start == end) {
                return node;
            }
            int mid = start + (end - start) / 2;
            node.left = buildTree(start, mid);
            node.right = buildTree(mid + 1, end);
            return node;
        }

        public int querySum(int start, int end) {
            return querySumHelper(root, start, end);
        }

        public int querySumHelper(SegmentTreeNode node, int start, int end) {
            if(node.start == start && node.end == end) {
                return node.sum;
            }
            int mid = node.start + (node.end - node.start) / 2;
            // node.start..........mid.......node.end;
            //              start.......end;
            int leftsum = 0, rightsum = 0;
            if(start <= mid) {
                leftsum = querySumHelper(node.left, start, Math.min(mid, end));
            }
            if(mid + 1 <= end) {
                rightsum = querySumHelper(node.right, Math.max(mid + 1, start), end);
            }
            return leftsum + rightsum;
        }

        public void add(int index, int value) {
            addHelper(root, index, value);
        }

        public void addHelper(SegmentTreeNode node, int index, int value) {
            if(node.start == node.end && node.end == index) {
                node.sum += value;
                return;
            }
            int mid = node.start + (node.end - node.start) / 2;
            if(index <= mid) {
                addHelper(node.left, index, value);
            }
            if(mid + 1 <= index) {
                addHelper(node.right, index, value);
            }
            node.sum = node.left.sum + node.right.sum;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值