Range Sum Query - Mutable -leetcode
새로운 것 이나 내 가 아직 잘 모 르 는 데이터 구 조 를 도입 했다.
SegmentTree。선분 수 또는 구간 수 라 고도 부른다.사실 구간 수 라 고 부 르 는 게 더 이해 가 돼 요.나무: 한 그루 의 나무 이 고 두 갈래 의 나무 입 니 다.선분: 나무의 모든 노드 는 하나의 선분 (또는 '구간' 이 라 고 부 르 는 것 이 더 > 이해 하기 쉽 고 구간 의 출발점 과 종점 은 보통 정수) 과 같은 층 의 노드 가 대표 하 는 구간 에 대응 하여 서로 겹 치지 않 습 니 다.잎 노드 의 구간 은 단위 길이 여서 더 이상 나 눌 수 없다.
선분 나 무 는 이 진 트 리 로 나무의 모든 결점 은 하나의 구간 [a, b] 을 나타 낸다.a, b 는 보통 정수 입 니 다.모든 잎 노드 는 단위 구간 을 표시 한다.모든 비 엽 결점 이 표시 하 는 결점 [a, b] 에 대해 왼쪽 아들 이 표시 하 는 구간 은 [a, (a + b) / 2] 이 고 오른쪽 아들 이 표시 하 는 구간 은 [(a + b) / 2, b] (나눗셈 제거) 이다.
선분 트 리 의 기본 용도: 선분 트 리 는 구간 통계 와 관련 된 문제 에 적합 합 니 다. 예 를 들 어 일부 데 이 터 는 구간 에 따라 구분 할 수 있 고 구간 동태 에 따라 수정 할 수 있 으 며 구간 에 따라 여러 번 조회 해 야 합 니 다. 그러면 선분 트 리 를 사용 하면 비교적 빠 른 조회 속 도 를 얻 을 수 있 습 니 다.
선분 트 리 의 구축 createSeg / / 노드 v 를 뿌리 로 트 리 를 만 들 고 v 대응 구간 은 [l, r] {노드 v 에 대한 초기 화 if (l! = r) {v 의 왼쪽 아 이 를 뿌리 로 트 리 를 만 들 고 구간 은 [l, (l + r) / 2] v 의 오른쪽 아 이 를 뿌리 로 트 리 를 만 들 고 구간 은 [(l + r) / 2 + 1, r]}}}} 이 문 제 는 제 가 원래 의 방법 을 사용 하여 시간 복잡 도의 요 구 를 만족 시 키 지 못 하고 토론 구역 에 따라 정 리 된 답 입 니 다.
다음은 leetcode 에서 토론 구 의 한 네티즌 의 코드 입 니 다.
public class NumArray {
class SegmentTreeNode {
int start, end;
SegmentTreeNode left, right;
int sum;
public SegmentTreeNode(int start, int end) {
this.start = start;
this.end = end;
this.left = null;
this.right = null;
this.sum = 0;
}
}// , 。 。
SegmentTreeNode root = null;// ,
public NumArray(int[] nums) {
root = buildTree(nums, 0, nums.length-1);//
}
private SegmentTreeNode buildTree(int[] nums, int start, int end) {
if (start > end) {// ,
return null;
} else {
SegmentTreeNode ret = new SegmentTreeNode(start, end);//
if (start == end) {// start end , 。 , sum nums[start]。
ret.sum = nums[start];
} else {
int mid = start + (end - start) / 2;// , 。
ret.left = buildTree(nums, start, mid);
ret.right = buildTree(nums, mid + 1, end);
ret.sum = ret.left.sum + ret.right.sum;
}
return ret;
}
}
void update(int i, int val) {
update(root, i, val);
}
void update(SegmentTreeNode root, int pos, int val) {
if (root.start == root.end) {// , , 。
root.sum = val;
} else {
int mid = root.start + (root.end - root.start) / 2;
if (pos <= mid) {
update(root.left, pos, val);
} else {
update(root.right, pos, val);
}
root.sum = root.left.sum + root.right.sum;// sum 。
}
}
public int sumRange(int i, int j) {
return sumRange(root, i, j);
}
public int sumRange(SegmentTreeNode root, int start, int end) {
if (root.end == end && root.start == start) {// ,
return root.sum;
} else {// ,
int mid = root.start + (root.end - root.start) / 2;
if (end <= mid) {//
return sumRange(root.left, start, end);
} else if (start >= mid+1) {//
return sumRange(root.right, start, end);
} else { // , 。
return sumRange(root.right, mid+1, end) + sumRange(root.left, start, mid);
}
}
}
내 가 다시 쓴 코드 는 한 번 에 한 번 debug 를 거 쳐 다른 사람의 한 줄 에 한 줄 씩 두 번 더 보고 나 서 야 다 보 았 다. 조금의 의미 도 다 르 게 해 서 는 안 된다. 이것 이 바로 프로그램 이다.
public class NumArray {
private class Node{//tree node
Node left,right;//left and right child
int start,end; //the range charged by the node
int sum; //sum of the range charged by the node
public Node(){
left=right=null;
sum=0;
}
}
Node root=null; //root of the the tree for this problem
public NumArray(int[] nums) {//in this function, we shoule create a tree to hold all elements in nums and calc sum.which achieved by recursion.
int length=nums.length;
root=makeATree(nums,0,length-1);
}
private Node makeATree(int[] nums,int start,int end){
if(start>end){return null;}
Node tree=new Node();
tree.start=start;
tree.end=end;
if(start==end){
tree.sum=nums[start];
}
else { //if this is the leaf node
int mid=start+(end-start)/2;
tree.left=makeATree(nums,start,mid);
tree.right=makeATree(nums,mid+1,end);
tree.sum=tree.left.sum+tree.right.sum;
}
return tree;
}
void update(int i, int val) {
myUp(i,val,root);
}
private void myUp(int i,int val,Node tree){
if(tree.start==tree.end){
tree.sum=val;
}
else{
int mid=tree.start+(tree.end-tree.start)/2;
if(i<=mid){
myUp(i,val,tree.left);
}else {
myUp(i,val,tree.right);
}
tree.sum=tree.left.sum+tree.right.sum;
}
}
public int sumRange(int i, int j) {
return calRange(i,j,root);
}
private int calRange(int start,int end,Node tree){
if(start==tree.start&&end==tree.end){//edge case and leaf node case
return tree.sum;
}else{ //if not the leaf node
int mid =tree.start+(tree.end-tree.start)/2;// tree.start tree.end , , start end 。
if(end<=mid){ //in total left
return calRange(start,end,tree.left);//
}else if(start>=mid+1){ // , mid+1 //in total right
return calRange(start,end,tree.right);
}else{ //in part of the node range involve mid
return calRange(start,mid,tree.left)+calRange(mid+1,end,tree.right);
}
}
}
}
총결산
새로운 데이터 구 조 를 도입 하 는 것 은 적응 되 지 않 을 수 밖 에 없다. 흐리멍덩 한 데이터 구조의 개념 을 가지 고 인 코딩 을 하면 오류 가 발생 할 수 있다. 종이 로 약 도 를 그 려 내부 의 운영 체 제 를 볼 수 있다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.