日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

leetcode307. Range Sum Query - Mutable

發(fā)布時間:2025/3/19 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 leetcode307. Range Sum Query - Mutable 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目要求

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.The update(i, val) function modifies nums by updating the element at index i to val. Example: Given nums = [1, 3, 5]sumRange(0, 2) -> 9 update(1, 2) sumRange(0, 2) -> 8 Note: The array is only modifiable by the update function. You may assume the number of calls to update and sumRange function is distributed evenly.

可以先參考數(shù)組不發(fā)生變動時的題目。

這里的難度在于數(shù)組可以在中間出現(xiàn)變動,那么面對大容量數(shù)組的時候如何選擇一個合適的數(shù)據(jù)結(jié)構(gòu)及很重要。

思路一:map緩存

最開始我們有兩種直觀的想法,一種是在插入時同時更新后面所有的和,這意味著O(n)的插入復(fù)雜度和O(1)的讀取復(fù)雜度。我決定選擇第二種方式,也就是采用類似日志的形式記錄下每一次的變更。這樣當(dāng)我們讀取的時候,再遍歷日志,將相關(guān)的變更結(jié)果添加到當(dāng)前的數(shù)值上。缺點是,變更很多以及數(shù)組很龐大時,效率依然很差。

這個方法超時了。

private int[] sum;private int[] nums;private Map<Integer, Integer> log;public NumArray(int[] nums) {this.nums = nums;sum = new int[nums.length];for(int i = 0 ; i<nums.length ; i++){if(i==0) sum[i] = nums[i];else sum[i] = sum[i-1] + nums[i];}log = new HashMap<Integer, Integer>();}public void update(int i, int val) {log.put(i, val - nums[i]);}public int sumRange(int i, int j) {int origin = 0;if(i==0) origin = sum[j];else origin = sum[j] - sum[i-1];for(Integer key : log.keySet()){if(key>=i && key <= j){origin += log.get(key);}}return origin;}

思路二:Segment Tree

我們將一個數(shù)組轉(zhuǎn)化為一棵樹,其中當(dāng)前的數(shù)組被均勻的分割并且分別用左子數(shù)組和右子數(shù)組構(gòu)建左子樹和右子樹。最后的葉節(jié)點為當(dāng)前數(shù)組的值,非葉結(jié)點則記錄了子數(shù)組的范圍以及該子數(shù)組中所有元素的和。

舉個例子說明一下:
假設(shè)當(dāng)前的數(shù)組為[1,2,5],則構(gòu)成的Segment Tree為:

8/ \3 5/ \1 2

這里先將[1,2,5]分割為[1,2]和[5]兩個子數(shù)組,然后分別構(gòu)造子樹。最后的樹如上所示。

class SegmentTreeNode{int start;int end;SegmentTreeNode left;SegmentTreeNode right;int sum;public SegmentTreeNode(int start, int end){this.start = start;this.end = end;}}private SegmentTreeNode buildSegmentTree(int[] nums, int start, int end){if(start > end) return null;SegmentTreeNode cur = new SegmentTreeNode(start, end);if(start == end) cur.sum = nums[start];else{int mid = (start + end) / 2;cur.left = buildSegmentTree(nums, start, mid);cur.right = buildSegmentTree(nums, mid+1, end);cur.sum = cur.left.sum + cur.right.sum;}return cur;}private SegmentTreeNode root;public NumArray(int[] nums) {this.root = buildSegmentTree(nums, 0, nums.length-1);}public void update(int i, int val) {update(root, i, val);}private void update(SegmentTreeNode root, int position, int val){if(root.start == root.end){root.sum = val;}else{int mid = (root.start + root.end) / 2;if(position <= mid){update(root.left, position, val);}else{update(root.right, position, val);}root.sum = root.left.sum + root.right.sum;}}public int sumRange(int i, int j) {return sumRange(root, i, j);} public int sumRange(SegmentTreeNode root, int i, int j){if(root.start==i && root.end==j){return root.sum;}int mid = (root.start + root.end )/2;if(j<=mid){return sumRange(root.left, i, j);}else if(i>mid){return sumRange(root.right, i, j);}else{return sumRange(root.left, i, mid) + sumRange(root.right, mid+1, j);}}

要想了解更多關(guān)于Segment Tree,請參考這篇文章。

思路三:Binary Indexed Tree

網(wǎng)上有非常多的關(guān)于二進制索引數(shù)樹的教程。它是一個非常輕量級的數(shù)據(jù)結(jié)構(gòu),而且?guī)缀蹙褪菫檫@種題目量身打造。可以先從這篇文章和這篇文章了解一下。

class NumArray {int[] nums;int[] BIT;int n;public NumArray(int[] nums) {this.nums = nums;n = nums.length;BIT = new int[n + 1];for (int i = 0; i < n; i++)init(i, nums[i]);}//每次更新當(dāng)前節(jié)點的同時更新父節(jié)點public void init(int i, int val) {i++;while (i <= n) {BIT[i] += val;i += (i & -i);}}//更新當(dāng)前節(jié)點,同時將改變傳遞給父節(jié)點void update(int i, int val) {int diff = val - nums[i];nums[i] = val;init(i, diff);}//public int getSum(int i) {int sum = 0;i++;while (i > 0) {sum += BIT[i];i -= (i & -i);}return sum;}public int sumRange(int i, int j) {return getSum(j) - getSum(i - 1);}}


想要了解更多開發(fā)技術(shù),面試教程以及互聯(lián)網(wǎng)公司內(nèi)推,歡迎關(guān)注我的微信公眾號!將會不定期的發(fā)放福利哦~

總結(jié)

以上是生活随笔為你收集整理的leetcode307. Range Sum Query - Mutable的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。