LeetCode 327. 区间和的个数

我会带着你远行 2022-10-29 03:13 264阅读 0赞

在这里插入图片描述

  1. //解法一:分治 68%
  2. class Solution {
  3. public int countRangeSum(int[] nums, int lower, int upper) {
  4. int n = nums.length;
  5. long[] sum = new long[n + 1];
  6. for(int i = 1; i <= n; i++){
  7. sum[i] = sum[i - 1] + nums[i - 1];
  8. }
  9. return countRangeSumRecursive(sum, lower, upper, 0, sum.length - 1);
  10. }
  11. public int countRangeSumRecursive(long[] sum, int lower, int upper, int left, int right){
  12. if(left == right)
  13. return 0;
  14. int mid = left + right >> 1;
  15. int n1 = countRangeSumRecursive(sum, lower, upper, left, mid);
  16. int n2 = countRangeSumRecursive(sum, lower, upper, mid + 1, right);
  17. int ret = n1 + n2;
  18. int i = left;
  19. int l = mid + 1, r = mid + 1;
  20. while(i <= mid){
  21. while(l <= right && sum[l] - sum[i] < lower) l++;
  22. while(r <= right && sum[r] - sum[i] <= upper) r++;
  23. ret += (r - l);
  24. i++;
  25. }
  26. int p = 0;
  27. int p1 = left, p2 = mid + 1;
  28. long[] sorted = new long[right - left + 1];
  29. while(p1 <= mid || p2 <= right){
  30. if(p1 > mid){
  31. sorted[p++] = sum[p2++];
  32. }else if(p2 > right){
  33. sorted[p++] = sum[p1++];
  34. }else{
  35. if (sum[p1] < sum[p2]) {
  36. sorted[p++] = sum[p1++];
  37. } else {
  38. sorted[p++] = sum[p2++];
  39. }
  40. }
  41. }
  42. for (int k = 0; k < sorted.length; k++) {
  43. sum[left + k] = sorted[k];
  44. }
  45. return ret;
  46. }
  47. }
  48. //解法二:树状数组
  49. class Solution {
  50. public int countRangeSum(int[] nums, int lower, int upper) {
  51. long sum = 0;
  52. long[] preSum = new long[nums.length + 1];
  53. for(int i = 0; i < nums.length; i++){
  54. sum += nums[i];
  55. preSum[i + 1] = sum;
  56. }
  57. Set<Long> allNumbers = new TreeSet<Long>();
  58. for(long x : preSum){
  59. allNumbers.add(x - lower);
  60. allNumbers.add(x - upper);
  61. allNumbers.add(x);
  62. }
  63. Map<Long, Integer> values = new HashMap<Long, Integer>();
  64. int idx = 1;
  65. for(long x : allNumbers){
  66. values.put(x, idx);
  67. idx++;
  68. }
  69. int ret = 0;
  70. BIT bit = new BIT(values.size() + 1);
  71. for(int i = 0; i < preSum.length; i++){
  72. int left = values.get(preSum[i] - upper), right = values.get(preSum[i] - lower);
  73. ret += bit.query(right) - bit.query(left - 1);
  74. bit.update(values.get(preSum[i]), 1);
  75. }
  76. return ret;
  77. }
  78. }
  79. class BIT {
  80. int[] tree;
  81. int n;
  82. public BIT(int n) {
  83. this.n = n;
  84. this.tree = new int[n + 1];
  85. }
  86. public static int lowbit(int x) {
  87. return x & (-x);
  88. }
  89. public void update(int x, int d) {
  90. while (x <= n) {
  91. tree[x] += d;
  92. x += lowbit(x);
  93. }
  94. }
  95. public int query(int x) {
  96. int ans = 0;
  97. while (x != 0) {
  98. ans += tree[x];
  99. x -= lowbit(x);
  100. }
  101. return ans;
  102. }
  103. }
  104. //解法三:线段树
  105. class Solution {
  106. public int countRangeSum(int[] nums, int lower, int upper) {
  107. long sum = 0;
  108. long[] preSum = new long[nums.length + 1];
  109. for (int i = 0; i < nums.length; ++i) {
  110. sum += nums[i];
  111. preSum[i + 1] = sum;
  112. }
  113. Set<Long> allNumbers = new TreeSet<Long>();
  114. for (long x : preSum) {
  115. allNumbers.add(x);
  116. allNumbers.add(x - lower);
  117. allNumbers.add(x - upper);
  118. }
  119. // 利用哈希表进行离散化
  120. Map<Long, Integer> values = new HashMap<Long, Integer>();
  121. int idx = 0;
  122. for (long x : allNumbers) {
  123. values.put(x, idx);
  124. idx++;
  125. }
  126. int[] a = new int[values.size()];
  127. TreeNode root = buildTree(a, 0, values.size() - 1);
  128. int ret = 0;
  129. for (long x : preSum) {
  130. int left = values.get(x - upper), right = values.get(x - lower);
  131. ret += queryTree(root, left, right);
  132. updateTree(root, values.get(x), 1);
  133. }
  134. return ret;
  135. }
  136. class TreeNode {
  137. int val;
  138. int start;
  139. int end;
  140. TreeNode left;
  141. TreeNode right;
  142. public TreeNode(int start, int end) {
  143. left = null;
  144. right = null;
  145. this.start = start;
  146. this.end = end;
  147. }
  148. }
  149. private TreeNode buildTree(int[] nums, int start, int end) {
  150. if (start > end) return null;
  151. TreeNode curr = new TreeNode(start, end);
  152. if (start == end) curr.val = nums[start];
  153. else {
  154. int mid = start + (end - start) / 2;
  155. curr.left = buildTree(nums, start, mid);
  156. curr.right = buildTree(nums, mid + 1, end);
  157. curr.val = curr.left.val + curr.right.val;
  158. }
  159. return curr;
  160. }
  161. public void updateTree(TreeNode node, int i, int val) {
  162. if (node.start == node.end) {
  163. node.val += val;
  164. } else {
  165. int mid = node.start + (node.end - node.start) / 2;
  166. if (i <= mid) updateTree(node.left, i, val);
  167. else updateTree(node.right, i, val);
  168. node.val = node.left.val + node.right.val;
  169. }
  170. }
  171. public int queryTree(TreeNode node, int i, int j) {
  172. if(i > j)
  173. return 0;
  174. if (node.start == i && node.end == j) return node.val;
  175. else {
  176. int mid = node.start + (node.end - node.start) / 2;
  177. if (j <= mid) {
  178. return queryTree(node.left, i, j);
  179. } else if (i >= (mid + 1)) {
  180. return queryTree(node.right, i, j);
  181. } else {
  182. return queryTree(node.left, i, mid) + queryTree(node.right, mid + 1, j);
  183. }
  184. }
  185. }
  186. }

发表评论

表情:
评论列表 (有 0 条评论,264人围观)

还没有评论,来说两句吧...

相关阅读