LeetCode 327. Count of Range Sum(区间和计数)
来源:互联网 发布:淘宝阿丑体育 编辑:程序博客网 时间:2024/06/13 09:38
原题网址: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 = -2
, upper = 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<nums.length; i++) sums[i] = sums[i-1] + nums[i]; int total = 0; TreeMap<Long, Integer> treemap = new TreeMap<>(); for(int i=0; i<nums.length; i++) { if (lower <= sums[i] && sums[i] <= upper) total ++; for(Integer count: treemap.subMap(sums[i]-upper, true, sums[i]-lower, true).values()) { total += count; } Integer count = treemap.get(sums[i]); if (count == null) count = 1; else count ++; treemap.put(sums[i], count); } return total; }}
方法二:使用二叉搜索树(相当于方法一的自己实现)
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<nums.length; i++) sums[i] = sums[i-1] + nums[i]; root = new Node(nums[0]); int count = 0; for(int i=0; i<nums.length; i++) { // System.out.printf("i=%d, sums[i]=%d\n", i, sums[i]); if (lower <= sums[i] && sums[i] <= upper) { count ++; // System.out.printf("1. count=%d\n", count); } count += sub(root, sums[i]-upper, sums[i]-lower); // System.out.printf("2. count=%d\n", count); insert(root, sums[i]); } return count; }}class Node { long val; int count; Node left, right; Node(long val) { this.val = val; }}
方法三:改进的二叉搜索树(保存左子树节点数量)
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<m) node.left = build(nums, from, m-1); if (m<to) node.right = build(nums, m+1, to); return node; } private void update(Node node, long val) { if (node == null) return; if (val < node.val) { node.count ++; update(node.left, val); } else if (val > 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<nums.length; i++) sums[i] = sums[i-1] + nums[i]; Set<Long> set = new HashSet<>(); for(int i=0; i<nums.length; i++) set.add(sums[i]); long[] unique = new long[set.size()]; int u=0; for(long s: set) unique[u++] = s; Arrays.sort(unique); Node root = build(unique, 0, unique.length-1); int count = 0; for(int i=0; i<sums.length; i++) { if (lower <= sums[i] && sums[i] <= upper) count ++; count += smaller(root, sums[i]-lower) - smaller(root, sums[i]-upper-1); update(root, sums[i]); } return count; }}class Node { long val; int count; Node left, right; Node(long val) { this.val = val; }}
方法四:使用分段树,通过预先排序实现数的平衡。
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<Long> set = new HashSet<>(); set.add(sums[0]); for(int i=1; i<nums.length; i++) { sums[i] = sums[i-1] + nums[i]; set.add(sums[i]); } long[] ranges = new long[set.size()]; int r=0; for(long s: set) ranges[r++] = s; Arrays.sort(ranges); root = build(ranges, 0, ranges.length-1); int count = 0; for(int i=0; i<sums.length; i++) { if (lower <= sums[i] && sums[i] <= upper) count ++; count += query(root, sums[i]-upper, sums[i]-lower); update(root, sums[i]); } return count; }}class Node { long min, max; int count; Node left, right; Node(long min, long max) { this.min = min; this.max = max; }}
方法五:使用合并排序发实现分治策略。
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; i<merged.length; i++) { if (j>m) 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<nums.length; i++) sums[i] = sums[i-1] + nums[i]; return sort(sums, 0, sums.length-1, lower, upper); }}
方法六:树状数组。
未实现,留待下次。
二叉树不一定要用指针实现,可以用数组实现。
0 0
- LeetCode 327. Count of Range Sum(区间和计数)
- leetcode : 327. Count of Range Sum : 连续和在指定区间内
- leetcode 327. Count of Range Sum 字段和问题
- <LeetCode OJ> 327. Count of Range Sum
- leetcode 327. Count of Range Sum
- Leetcode 327. Count of Range Sum[hard]
- LeetCode 327. Count of Range Sum
- leetcode 327.Count of Range Sum
- LeetCode 327. Count of Range Sum
- LeetCode 327. Count of Range Sum
- leetcode 327. Count of Range Sum
- [leetcode]327. Count of Range Sum
- leetcode 327. Count of Range Sum
- leetcode Count of Range Sum
- LeetCode Count of Range Sum
- [LeetCode]Count of Range Sum
- Leetcode Count of Range Sum
- leetcode Count of Range Sum
- Java目录
- BJTU 1729 Ryan的弹幕游戏(BFS)
- sql执行顺序
- win10连上wifi却上不了网
- 虚拟币开发
- LeetCode 327. Count of Range Sum(区间和计数)
- 虚幻4 材质的编译。
- MySQL之终端Terminal(dos界面)管理数据库、数据表、数据的基本操作
- 比特币开发教程
- 我的项目收尾阶段遇到的一些问题
- 【VS开发】单文档中往视图中加入控件
- python_笔记12_匿名函数
- 虚拟货币开发教程
- 【VS开发】CFormView