[LintCode]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, 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.

这个题目并不难。也不是一个很好的题目。有为了做题而做题的嫌疑。但是是一个综合练习seg-tree的题目。

在之前的练习里已经熟悉了seg-tree的build 与 query方法,这个题目有一点地方比较绕,尽管知道了 构造tree的root范围应该是start = 0, end = 10000,

一开始花了很久我也没有想到的是,如果我们事先建好了整个tree,最后再去query的话,是无法得到正确结果的,我们只能得到整个array里比某元素小的数的个数。

所以这棵树必须是边建立边查询的(array 从左往右扫),这样才能保证每次查询时候,树里只有其左边部分信息,也就是符合了要求。



public class Solution {
   /**
     * @param A: An integer array
     * @return: Count the number of element before this element 'ai' is 
     *          smaller than it and return count number array
     */ 
    class SegmentTreeNode {
        public int start, end;
        public int count;
        public SegmentTreeNode left, right;
        public SegmentTreeNode(int start, int end, int count) {
              this.start = start;
              this.end = end;
              this.count = count;
              this.left = this.right = null;
        }
    }
    SegmentTreeNode root;
    public SegmentTreeNode build(int start, int end) {
        SegmentTreeNode root = new SegmentTreeNode(start, end, 0);
        if(start != end) {
            int mid = (start + end) / 2;
            root.left = build(start, mid);
            root.right = build(mid+1, end);
        } else {
            root.count =  0;
        }
        return root;
    }
    public int querySegmentTree(SegmentTreeNode root, int start, int end) {
        if(start == root.start && root.end == end) { 
            return root.count;
        }
        int mid = (root.start + root.end)/2;
        int leftcount = 0, rightcount = 0;
        if(start <= mid)
            leftcount = querySegmentTree(root.left, start, Math.min(mid,end));
        if(end > mid)
            rightcount = querySegmentTree(root.right, Math.max(start,mid+1), end);
        return leftcount + rightcount;
    }
    
    public void modifySegmentTree(SegmentTreeNode root, int index, int value) {
        if(root.start == index && root.end == index) { 
            root.count += value;
            return;
        }
        
        int mid = (root.start + root.end) / 2;
        //end up in left part
        if(root.start <= index && index <=mid) {
            modifySegmentTree(root.left, index, value);
        }
        //end up in right part
        if(mid < index && index <= root.end) {
            modifySegmentTree(root.right, index, value);
        }
        //otherwise no effect on current subtree
        
        root.count = root.left.count + root.right.count;
    }
    //Notice, this method will only be used once. The built up tree can't be re-used
    //We are updating(building value part) the tree while we are scanning over the array,that's why we can  track left part because so far we only have info. on left part.which means after processing one more entry, the tree now can't give right info on previous entries any more.
    
    public ArrayList
   
   
    
     countOfSmallerNumberII(int[] A) {
        root = build(0, 10000);
        ArrayList
    
    
     
      ans = new ArrayList
     
     
      
      ();
        int res;
        for(int i = 0; i < A.length; i++) {
            res = 0;
            if(A[i] > 0) {
                //get count of values smaller than A[i] and in the front part of array
                res = querySegmentTree(root, 0, A[i]-1);
            }
            //update current value into tree structure
            modifySegmentTree(root, A[i], 1);
            ans.add(res);
        }
        return ans;
    }
}
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值