www.91084.com

GVKun编程网logo

树状数组(Binary Indexed Tree)(树状数组区间修改区间查询)

14

以上就是给各位分享树状数组,其中也会对BinaryIndexedTree进行解释,同时本文还将给你拓展501.FindModeinBinarySearchTree、501.FindModeinBina

以上就是给各位分享树状数组,其中也会对Binary Indexed Tree进行解释,同时本文还将给你拓展501. Find Mode in Binary Search Tree、501. Find Mode in Binary Search Tree【LeetCode by java】、Balanced Binary Tree - LeetCode、Balanced Binary Tree-LeetCode等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

树状数组(Binary Indexed Tree)(树状数组区间修改区间查询)

树状数组(Binary Indexed Tree)(树状数组区间修改区间查询)

  树状数组(Binary Indexed Tree,BIT) 是能够完成下述操作的数据结构。

  给一个初始值全为 0 的数列 a1,a2,...,an

  (1)给定 i,计算 a1+a2+...+ai

  (2)给定 i 和 x,执行 ai += x

1.基于线段树的实现

  如果使用线段树,只需要做少许修改就可以实现这两个功能。线段树的每个节点上维护的是对应区间的和。

  

分享图片

  接下来看如何计算从 s 到 t 的和(as + as+1 + ... + at)。在基于线段树的实现这个和是可以直接求得的。

  但是如果我们能够计算(从 1 到 t 的和) - (从 1 到 s - 1 的和),同样可以得到 s 到 t 的和。也就是说,只要对于任意 i,我们都能计算出 1 到 i 的部分和就可以了。

  可以发现,线段树上的每个节点的右儿子的值都不需要了(在计算时如果要使用这个点的值,那么它的左边的兄弟的值也一定会用到,这个时候只需要使用它们的父亲的值就可以了)。

  

分享图片

 

  基于上面的思路得到的数据结构就是 BIT。比起线段树,BIT实现起来更方便,速度也更快。

2. BIT的结构

  BIT 使用数组维护下图所示的部分和

   

分享图片

  也就是把线段树中不需要的节点去掉之后,再把剩下的节点对应到数组中。对比每个节点对应的区间的长度和节点编号的二进制表示。以 1 结尾的 1, 3, 5, 7 的长度是1, 最后有 1 个 0 的2, 6 的长度是2,最后有两个 0 的 4 的长度是 4 .... 这样,编号的二进制表示就能够和区间非常容易地对应起来。利用这个性质,BIT 可以通过非常简单的位运算实现。

3. BIT的求和

   计算前 i 项的和需要从 i 开始,不断把当前位置 i 的值加入到结果中, 并从 i 中减去 i 的二进制最低非 0 位对应的幂,直到 i 变为 0 为止。i 的二进制的最后一个 1 可以通过 i & - i 得到。

  

分享图片

4.BIT的值的更新

  使第 i 项的值增加 x 需要从 i 开始,不断把当前位置 i 的值增加 x, 并把 i 的二进制最低非 0 位对应的幂加到 i 上。

    

分享图片

5. BIT的复杂度

  总共需要对O(log n)个值进行操作,所以复杂度是O(log n)。

6. BIT的实现

   提一下 i -= i & -i 可以写为 i = i &(i - 1)

// [1,n]
int bit[MAX_N + 1],n;

int sum(int i) {
    int s = 0;
    while (i > 0) {
        s += bit[i];
        i -= i & -i;
    }
    return s;
} 

void add(int i,int x) {
    while (i <= n) {
        bit[i] += x;
        i += i & -i;
    }
}

  //本来想把代码补完整的。。参考线段树就行,但是后面会有综述我就不补了

7.  二维BIT

   BIT 可以方便地扩展到二维的情况。对于 W * H 的二维 BIT 只需建立 H 个大小为 x 轴方向元素个数 W 的 BIT,然后把这些 BIT 通过 y 轴方向的 BIT 管理起来就可以了。也就是说,y 轴方向的 BIT 的每个元素不是整数,而是一个 x 轴方向的 BIT。这样所有的操作的复杂度都是 O(log W * log H)。用同样的方法可扩展到更高的维度。

   // emm 

8. 需要运用 BIT 的问题

  

分享图片

  

分享图片

  冒泡排序的复杂度是 O(n2),所以无法模拟过程。选用适当的数据结构可以解决这个问题。

  所求的交换次数等价于 满足 i < j,ai > aj  的 i  的个数,(这种数对的个数叫做逆序数)。而对于每一个 j,如果能够快速求出满足 i < j,ai > aj  的 i  的个数,那么问题就解决了。我们构建一个值的范围是 1 ~ n 的 BIT,按照 j = 0, 1, 2, ..., n-1 的顺序进行如下操作。

  (1)把 j - (BIT查询得到的前 aj 项的和)加到答案中

  (2)把 BIT 中 aj 位置上的值加 1

  对于每一个 j, (BIT查询得到的前 aj 项的和)就是满足i < j,ai > aj  的 i  的个数。因此把这个值从 j 中减去之后,得到的就是满足 i < j,ai > aj  的 i  的个数。由于对于每一个 j 的复杂度是O(log n),所以整个算法的复杂度是O(n log n)。

  // 但实际上实现计算逆序数更简单的算法是通过分治思想利用归并排序计算

typedef long long ll;
int n,a[MAX_N];
//省略BIT部分代码 
void solve() {
    ll ans = 0;
    for (int j = 0; j < n; j++) {
        ans += j - sum(a[j]);
        add(a[j],1);
    }
    printf("%lld\n",ans);
} 

 

  

分享图片

 

   树状数组可以高效地求出连续的一段元素之和或者更新单个元素的值。但是无法高效地给某一个区间里的所有元素同时加上一个值。因此,本题无法直接使用树状数组。在这里先考虑利用线段树来求解,然后再考虑改造树状数组来求解。

  对于每个节点,维护有该节点对应的区间的和,那么就可以在 O(log n)时间内

501. Find Mode in Binary Search Tree

Given a binary search tree (BST) with duplicates,find all the mode(s) (the most frequently occurred element) in the given BST.
Assume a BST is defined as follows:
* The left subtree of a node contains only nodes with keys less than or equal to the node‘s key.
* The right subtree of a node contains only nodes with keys greater than or equal to the node‘s key.
* Both the left and right subtrees must also be binary search trees.
 
For example:?Given BST [1,null,2,2],1
         2
    /
   2
 
return [2].
Note: If a tree has more than one mode,you can return them in any order.
Follow up: Could you do that without using any extra space? (Assume that the implicit stack space incurred due to recursion does not count).



见到BST就想到中序遍历。这个题中的BST是可以包含相同的元素的,题目的要求就是找出相同的元素出现次数最多的是哪几个。那么就可以先进行中序遍历得到有序的排列,如果两个相邻的元素相同,那么这个就是连续的,找出连续最多的即可。题目思路就是BST的中序遍历加上最长连续相同子序列。

题目建议不要用附加空间hash等,方法是计算了两次,一次是统计最大的模式出现的次数,第二次的时候构建出来了数组,然后把出现次数等于最大模式次数的数字放到数组的对应位置。

/**
 * DeFinition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public int[] findMode(TreeNode root) {
        inorder(root);
        modes = new int[modeCount];
        currCount = 0;
        modeCount = 0;
        inorder(root);
        return modes;
    }

    int currVal = 0;
    int currCount = 0;
    int maxCount = 0;
    int modeCount = 0;

    int[] modes;

    public void handleValue(int val){
        if(currVal != val){
            currVal = val;
            currCount = 0;
        }
        currCount++;
        if(currCount > maxCount){
            maxCount = currCount;
            modeCount = 1;
        }else if (currCount == maxCount){
            if(modes != null){
                modes[modeCount] = currVal;
            }
            modeCount++;
        }
    }

    public void inorder(TreeNode root){
        if(root == null){
            return;
        }
        inorder(root.left);
        handleValue(root.val);
        inorder(root.right);
    }
}
--------------------- 
作者:负雪明烛 
来源:CSDN 
原文:https://blog.csdn.net/fuxuemingzhu/article/details/71124600 
版权声明:本文为博主原创文章,转载请附上博文链接!

501. Find Mode in Binary Search Tree【LeetCode by java】

Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred element) in the given BST.

Assume a BST is defined as follows:

  • The left subtree of a node contains only nodes with keys less than or equal to the node''s key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node''s key.
  • Both the left and right subtrees must also be binary search trees.

 

For example:
Given BST [1,null,2,2],

   1
    \
     2
    /
   2

 

return [2].

Note: If a tree has more than one mode, you can return them in any order.

Follow up: Could you do that without using any extra space? (Assume that the implicit stack space incurred due to recursion does not count).


 
解题:给一个二叉查找树,返回出现次数最多的元素(众数)。并且要求不使用额外的空间,要求结果以数组的形式返回。我使用了一个ArrayList,有额外的空间消耗,虽然不满足条件,但是比较简单方便。当然也可以把数组定义为成员变量,由于数组的长度不知道,还得定义一个末尾指针,太麻烦,不如用集合。思路是,遍历BST,由于其本身的性质,遍历的过程中得到的序列,就是一个有序序列。定一个max用来保存出现做多的次数,pre记录父节点,如果没有,则为空。再定义一个res的集合保存结果,定一个cns保存当前出现最多的次数(暂时),然后不断地比较cns和max的值,随时更新res结果集,代码如下:
 1 /**
 2  * Definition for a binary tree node.
 3  * public class TreeNode {
 4  *     int val;
 5  *     TreeNode left;
 6  *     TreeNode right;
 7  *     TreeNode(int x) { val = x; }
 8  * }
 9  */
10 class Solution {
11     ArrayList<Integer>res = null;
12     TreeNode pre = null;
13     int max = 0;
14     int cns = 1;
15     public int[] findMode(TreeNode root) {
16         //存放结果
17         res = new ArrayList<Integer>();
18         middle_search(root);
19         int[] arr =new int[res.size()]; 
20         for(int i =0; i < arr.length; i++)
21             arr[i] = res.get(i);
22         return arr;
23     }
24     public void middle_search(TreeNode root) {
25         if(root == null)
26             return ;
27         middle_search(root.left);    
28         //处理根结点
29         if(pre != null){  //有父节点
30             if(root.val == pre.val)
31                 cns++;
32             else cns = 1;
33         }
34         if(cns >= max){
35             if(cns > max)
36                res.clear();
37             max = cns;
38             res.add(root.val);
39         }
40         pre = root;
41         
42         middle_search(root.right);
43     }
44 }

 

 
 

Balanced Binary Tree - LeetCode

Balanced Binary Tree - LeetCode

目录

  • 题目链接
  • 注意点
  • 解法
  • 小结

题目链接

Balanced Binary Tree - LeetCode

注意点

  • 不要访问空结点

解法

解法一:getDep用于求各个点深度的,然后对每个节点的两个子树来比较深度差,时间复杂度为O(NlgN)。

/**
 * DeFinition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x),left(NULL),right(NULL) {}
 * };
 */
class Solution {
public:
    int getDep(TreeNode* root)
    {
        if (!root) return 0;
        return 1 + max(getDep(root->left),getDep(root->right));
    }
    bool isBalanced(TreeNode* root) {
        if(!root) return true;
        if(abs(getDep(root->left)-getDep(root->right)) > 1) return false;
        return isBalanced(root->left) && isBalanced(root->right);
    }
};

分享图片

小结

  • avl的子树高度差不超过1

Balanced Binary Tree-LeetCode

Balanced Binary Tree-LeetCode

Balanced Binary Tree

  -LeetCode

题目:

Given a binary tree, determine if it is height-balanced.

For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

分析:

这道题目是判断平衡二叉树的。

我们可以看到,平衡二叉树 是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

通过递归,我们来通过判断左右子树的高度差是否大于1来判断这棵子树是否是平衡二叉树,最终能判断整个树是否是平衡二叉树。

代码:

# Definition for a  binary tree node
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    # @param root, a tree node
    # @return a boolean
    def isBalanced(self, root):
        if not root:
            return True
        if abs(self.height(root.left)-self.height(root.right))>1:
            return False
        else:
            return self.isBalanced(root.left) and self.isBalanced(root.right)
            
    # calculate the height of tree
    def height(self,root):
        if root == None:
            return 0
        return 1+max(self.height(root.left),self.height(root.right))

关于树状数组Binary Indexed Tree的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于501. Find Mode in Binary Search Tree、501. Find Mode in Binary Search Tree【LeetCode by java】、Balanced Binary Tree - LeetCode、Balanced Binary Tree-LeetCode等相关内容,可以在本站寻找。

本文标签: