493.Reverse-Pairs

493. Reverse Pairs

题目地址

https://leetcode.com/problems/reverse-pairs/

https://lotabout.me/2018/binary-indexed-tree/

题目描述

Given an array nums, we call (i, j) an important reverse pair if i < j and nums[i] > 2*nums[j].

You need to return the number of important reverse pairs in the given array.

Example1:
Input: [1,3,2,3,1]
Output: 2

Example2:
Input: [2,4,3,5,1]
Output: 3

Note:
The length of the given array will not exceed 50,000.
All the numbers in the input array are in the range of 32-bit integer.

代码

Approach #1 Merge Sort

class Solution {
    public int reversePairs(int[] nums) {
        int n = nums.length;

        if (nums == null || n == 0)     return 0;

        return mergeSort(nums, 0, n - 1);
    }

    private int mergeSort(int[] nums, int start, int end) {
        if (start >= end)   return 0;

        int mid = start + (end - start) / 2;
        int res = mergeSort(nums, start, mid) + mergeSort(nums, mid+1, end);

        int j = mid + 1;
        for (int i = start; i <= mid; i++) {
            while (j <= end && nums[i] / 2.0 > nums[j]) { // 防止溢出
                j++;
            }
            res += j - (mid + 1);
        }

        Arrays.sort(nums, start, end + 1);
        return res;
    }
}

Approach #2 BIT

class Solution {
    public int reversePairs(int[] nums) {
       int[] nums_copy = Arrays.copyOf(nums, nums.length);
        Arrays.sort(nums_copy);
        int[] bit = new int[nums_copy.length + 1];

        int cnt = 0;
        for (int num: nums) {
              // 利用BIT数据结构统计大于2*num的元素个数
            cnt += query(bit, index(nums_copy, num * 2L + 1));
             // 插入当前元素,这里index是num在copy中的下标
            insert(bit, index(nums_copy, num));
        }

        return cnt;
    }

    // 返回大于或者等于target的坐标,如果多个target返回第一个坐标
    private int index(int[] nums, long target) {
        int start = 0;
        int end = nums.length - 1;
        while (start <= end) {
            int mid = start + (end - start) / 2;
            if (nums[mid] >= target) {
                end = mid - 1;
            } else {
                start = mid + 1;
            }
        }
        // bit数组是以1为开始,所以返回start+1
        return start + 1;
    }

    private void insert(int[] bit, int i) {
        while (i > 0) {
            bit[i] ++;  // 比bit[i]大的个数
            i -= i & -i;
        }
    }

    private int query(int[] bit, int i) {
        int sum = 0;
        while (i < bit.length) {
            sum += bit[i];
            i += i & -i;
        }
        return sum;
    }
}

Approach #3 BST

可惜的是,我们自定义的树并不是一个平衡二叉树,在最坏的情况下会导致长链表,如果LeetCode上使用上述代码会导致TLE(Time Limit Exceeded)。

public class Solution {
    public int reversePairs(int[] nums) {
        Node root = null;
        int[] cnt = new int[1];
        for (int i = nums.length-1; i>=0; i--) {
            search(cnt, root, nums[i]/2.0);//search and count the partially built tree
            root = build(nums[i], root);//add nums[i] to BST
        }
        return cnt[0];
    }

    private void search(int[] cnt, Node node, double target){
        if (node == null) return; 
        else if(target == node.val) cnt[0] += node.less;
        else if(target < node.val) search(cnt, node.left, target);
        else {
            cnt[0] += node.less + node.same; 
            search(cnt, node.right, target);
        }
    }

    private Node build(int val, Node n) {
        if (n == null) return new Node(val);
        else if (val == n.val) n.same+=1;
        else if (val > n.val) n.right = build(val, n.right);
        else {
            n.less += 1;
            n.left = build(val, n.left);
        }
        return n;
    }

    class Node{
        int val, less = 0, same = 1;//less: number of nodes that less than this node.val
        Node left, right;
        public Node(int v){
            this.val = v;
        }
    }
}

Last updated