美文网首页
8.17 - hard - 62

8.17 - hard - 62

作者: 健时总向乱中忙 | 来源:发表于2017-08-18 03:36 被阅读0次

    315. Count of Smaller Numbers After Self

    这道题主要有两种解法:segment tree和mergesort,两种解法都要好好掌握才好!

    方法1:利用segment tree,取array的最大值和最小值做为区间范围,然后记录当前范围内的count,从后往前loop整个序列,找到相应的区间以及count。如果数值过大则会TLE
    方法2: 利用segment tree,取array的长度做为segment tree的区间,然后要把所有值求set然后排序,并且记录它们区间比如说[5,2, 6,1],排序[1,2,5,6] 如果当前求2的时候,就是求[0,1]区间内所有元素的个数,如果求5的时候就是求[0,3]区间内所有元素的个数。然后从右到左依次1.计算元素个数,2.把元素加入到segment tree里面。
    方法3: 利用mergesort的性质,在mergesort的merge阶段,每有一次swap就是要count一次。
    方法4: 利用 index tree, index tree是啥我还不知道

    方法1

    class SegTreeNode(object):
        def __init__(self, min_val, max_val):
            self.min_val = min_val
            self.max_val = max_val
            self.count = 0
            self.left = None
            self.right = None
    
        @property
        def mid(self):
            return (self.max_val+self.min_val)/2
        
    class Solution(object):
        def countSmaller(self, nums):
            res = []
            if not nums:
                return res
            min_val = min(nums)
            max_val = max(nums)
            root = self.build(min_val, max_val)
    
            for i in range(len(nums)-1, -1, -1):
                res = [self.find(nums[i], root)] + res
                self.add(nums[i], root)
                #print root.count, root.left.count, root.right.count
    
            return res
        
        def build(self, min_val, max_val):
            if min_val <= max_val:
                root = SegTreeNode(min_val, max_val)
                if min_val == max_val:
                    return root
                root.left = self.build(min_val, root.mid)
                root.right = self.build(root.mid+1, max_val)
                return root
            else:
                return None
        
        
        def find(self, x, root):
            if not root:
                return 0
    
            if x > root.max_val:
                return root.count
            else:
                if x < root.mid:
                    return self.find(x, root.left);
                else:
                    return self.find(x, root.left) + self.find(x, root.right);
        
        def add(self, x, root):
            if x < root.min_val or x > root.max_val:
                return
           
            root.count += 1
            if root.min_val == root.max_val:
                return
            
            if x <= root.mid:
                self.add(x, root.left)
            else:
                self.add(x, root.right)
    

    方法2

    class SegmentTreeNode(object):
        def __init__(self, val, start, end):
            self.val = val
            self.start = start
            self.end = end
            self.left = None
            self.right = None
    
    
    class SegmentTree(object):
        def __init__(self, n):
            self.root = self.build(0, n - 1)
    
        def build(self, start, end):
            if start > end:
                return None
    
            root = SegmentTreeNode(0, start, end)
            if start == end:
                return root
    
            mid = (start + end)/2
            root.left = self.build(start, mid)
            root.right = self.build(mid+1, end)
            return root
    
        def update(self, i, val, root): # 更新val在当前root区间内的值个数,也就是说如果val在root区间内,则root.val += 1
            if i < root.start or i > root.end:
                return root.val
    
            if i == root.start == root.end:
                root.val += val
                return root.val
            root.val = self.update(i, val, root.left) + self.update(i, val, root.right)
            return root.val
    
        def cal(self, start, end, root): # 求区间0 ~ x-1的值得个数
            if end < root.start or start > root.end:
                return 0
    
            if start <= root.start and end >= root.end:
                return root.val
    
            return self.cal(start, end, root.left) + self.cal(start, end, root.right)
    
    
    class Solution(object):
        def countSmaller(self, nums):
            hashTable = {v: i for i, v in enumerate(sorted(set(nums)))}
            # print hashTable
            tree, r = SegmentTree(len(hashTable)), []
            for i in xrange(len(nums) - 1, -1, -1):
                r.append(tree.cal(0, hashTable[nums[i]] - 1, tree.root))
                tree.update(hashTable[nums[i]], 1, tree.root)
            return r[::-1]
    

    相关文章

      网友评论

          本文标题:8.17 - hard - 62

          本文链接:https://www.haomeiwen.com/subject/blxgrxtx.html