Java 演算法-區間求和I(線段樹)

weixin_33896726發表於2018-01-11

  我之前學過線段樹,掌握的不是很牢固,而這道題是線段樹,為了加深記憶,所以還是覺得有必要記錄下來,就當是對線段樹的一個複習。

題意:
給定一個整數陣列(下標由 0 到 n-1,其中 n 表示陣列的規模),以及一個查
詢列表。每一個查詢列表有兩個整數 [start, end] 。 對於每個查詢,計算出數
組中從下標 start 到 end 之間的數的總和,並返回在結果列表中。
樣例:
對於陣列 [1,2,7,8,5],查詢[(1,2),(0,4),(2,4)], 返回 [9,23,20]

1.解題思路

  這道題用線段樹數做起來不是很難,同時時間複雜度也不是很高。由於樓主之前學過線段樹,所以這裡不再詳細的講解什麼是線段樹。
  我們在構建線段樹時,向線段樹的每一個節點加一個屬性--sum,用來表示當前節點的範圍的數值總和。然後在使用線段樹的查詢就可以得到我們想要的值了。

(1).構建線段樹

private SegmentTreeNode build(int A[], int start ,int end) {
        SegmentTreeNode node = new SegmentTreeNode(start, end, A[0]);
        if(node.start == node.end) {
            node.sum = A[start];
            return node;
        }
        int mid = (node.start + node.end) / 2;
        node.left = build(A, start, mid);
        node.right = build(A, mid + 1, end);
        node.sum = node.left.sum + node.right.sum;
        return node;
    }

(2).查詢線段樹

private long query(SegmentTreeNode node, int start , int end) {
        if(start > end) {
            return 0;
        }
        if(node.start == start && node.end == end) {
            return node.sum;
        }
        int mid = (node.start + node.end) /  2;
        if(end <= mid) {
            return query(node.left, start, end);
        }
        else if(start > mid) {
            return query(node.right, start, end);
        }else {
            return query(node.left, start, mid) + query(node.right, mid + 1, end);
        }
    }

2.程式碼

public List<Long> intervalSum(int[] A, List<Interval> queries) {
        List<Long> list = new ArrayList<>();
        if(A.length == 0 || queries.size() == 0) {
            return list;
        }
        SegmentTreeNode node = build(A, 0, A.length - 1);
        
        for(int i = 0; i < queries.size(); i++) {
            list.add(query(node, queries.get(i).start, queries.get(i).end));
        }
        return list;
    }
    //構建線段樹
    private SegmentTreeNode build(int A[], int start ,int end) {
        SegmentTreeNode node = new SegmentTreeNode(start, end, A[0]);
        if(node.start == node.end) {
            node.sum = A[start];
            return node;
        }
        int mid = (node.start + node.end) / 2;
        node.left = build(A, start, mid);
        node.right = build(A, mid + 1, end);
        node.sum = node.left.sum + node.right.sum;
        return node;
    }
    //查詢線段樹
    private long query(SegmentTreeNode node, int start , int end) {
        if(start > end) {
            return 0;
        }
        if(node.start == start && node.end == end) {
            return node.sum;
        }
        int mid = (node.start + node.end) / 2;
        if(end <= mid) {
            return query(node.left, start, mid);
        }
        else if(start > mid) {
            return query(node.right, start, end);
        }else {
            return query(node.left, start, mid) + query(node.right, mid + 1, end);
        }
    }

相關文章