LeetCode 327. Count of Range Sum(区间和计数)

原题网址:https://leetcode.com/problems/count-of-range-sum/

Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.
Range sum S(i, j) is defined as the sum of the elements in nums between indices i and j (i ≤ j), inclusive.

Note:
A naive algorithm of O(n2) is trivial. You MUST do better than that.

Example:
Given nums = [-2, 5, -1]lower = -2upper = 2,
Return 3.
The three ranges are : [0, 0][2, 2][0, 2] and their respective sums are: -2, -1, 2.

方法一:使用TreeMap来保存每个前缀和的计数。

public class Solution {
    public int countRangeSum(int[] nums, int lower, int upper) {
        if (nums == null || nums.length==0) return 0;
        long[] sums = new long[nums.length];
        sums[0] = nums[0];
        for(int i=1; i treemap = new TreeMap<>();
        for(int i=0; i

方法二:使用二叉搜索树(相当于方法一的自己实现)

public class Solution {
    Node root;
    private int sub(Node node, long lower, long upper) {
        // System.out.printf("sub=%s, lower=%d, upper=%d\n", node==null?"null":Long.toString(node.val), lower, upper);
        if (node == null) return 0;
        if (node.val < lower) return sub(node.right, lower, upper);
        if (upper < node.val) return sub(node.left, lower, upper);
        return node.count + sub(node.left, lower, node.val-1) + sub(node.right, node.val+1, upper);
    }
    private void insert(Node node, long val) {
        if (node.val < val) {
            if (node.right == null) node.right = new Node(val);
            insert(node.right, val);
        } else if (val < node.val) {
            if (node.left == null) node.left = new Node(val);
            insert(node.left, val);
        } else {
            node.count ++;
        }
    }
    public int countRangeSum(int[] nums, int lower, int upper) {
        if (nums == null || nums.length == 0) return 0;
        long[] sums = new long[nums.length];
        sums[0] = nums[0];
        for(int i=1; i

方法三:改进的二叉搜索树(保存左子树节点数量)

public class Solution {
    private Node build(long[] nums, int from, int to) {
        if (from>to) return null;
        int m = (from+to)/2;
        Node node = new Node(nums[m]);
        if (from node.val) {
            update(node.right, val);
        } else {
            node.count ++;
        }
    }
    private int smaller(Node node, long val) {
        if (node == null) return 0;
        if (node.val <= val) {
            return node.count + smaller(node.right, val);
        } else {
            return smaller(node.left, val);
        }
    }
    public int countRangeSum(int[] nums, int lower, int upper) {
        if (nums == null || nums.length == 0) return 0;
        long[] sums = new long[nums.length];
        sums[0] = nums[0];
        for(int i=1; i set = new HashSet<>();
        for(int i=0; i

方法四:使用分段树,通过预先排序实现数的平衡。

public class Solution {
    private Node root;
    private Node build(long[] ranges, int min, int max) {
        if (min>max) return null;
        Node Node = new Node(ranges[min], ranges[max]);
        if (min==max) return Node;
        int m = (min+max)/2;
        Node.left = build(ranges, min, m);
        Node.right = build(ranges, m+1, max);
        return Node;
    }
    private void update(Node node, long val) {
        if (node == null) return;
        if (val < node.min || node.max < val) return;
        node.count ++;
        update(node.left, val);
        update(node.right, val);
    }
    private int query(Node node, long from, long to) {
        if (node==null) return 0;
        if (node.max < from || to < node.min) return 0;
        if (from <= node.min && node.max <= to) return node.count;
        return query(node.left, from, to) + query(node.right, from, to);
    }
    public int countRangeSum(int[] nums, int lower, int upper) {
        if (nums == null || nums.length == 0) return 0;
        long[] sums = new long[nums.length];
        sums[0] = nums[0];
        Set set = new HashSet<>();
        set.add(sums[0]);
        for(int i=1; i

方法五:使用合并排序发实现分治策略。

public class Solution {
    private int sort(long[] sums, int from, int to, int lower, int upper) {
        if (from > to) return 0;
        if (from == to) return (lower <= sums[from] && sums[from] <= upper) ? 1 : 0;
        int count = 0;
        int m = (from + to) / 2;
        count = sort(sums, from, m, lower, upper) + sort(sums, m+1, to, lower, upper);
        for(int i=from, j=m+1, k=m+1; i<=m; i++) {
            while (j<=to && sums[j] - sums[i] < lower) j++;
            while (k<=to && sums[k] - sums[i] <= upper) k++;
            count += k - j;
        }
        long[] merged = new long[to-from+1];
        int l=from, r=m+1;
        for(int i=0, j=from, k=m+1; im) merged[i] = sums[k++];
            else if (k>to) merged[i] = sums[j++];
            else if (sums[j] <= sums[k]) merged[i] = sums[j++];
            else merged[i] = sums[k++];
        }
        System.arraycopy(merged, 0, sums, from, merged.length);
        return count;
    }
    public int countRangeSum(int[] nums, int lower, int upper) {
        if (nums == null || nums.length == 0) return 0;
        long[] sums = new long[nums.length];
        sums[0] = nums[0];
        for(int i=1; i

方法六:树状数组。

未实现,留待下次。

二叉树不一定要用指针实现,可以用数组实现。

你可能感兴趣的:(区间,二叉搜索树,数组,有序映射,分治策略,困难,段落,求和,分段树,树状数组,经典,合并排序,前缀和,区间和,多个指针,齐头并进)