Discretization and tree arrays

Today we will first talk about what is called discretization (simple mapping relationship)

1. Discretization

1. Concept : It is to map an infinite space to a limited space (commonly understood as reducing the data accordingly). For a better understanding, please see the following figure:

       Given two straight lines A and B, do you think the two straight lines have the same length? Whether we look at it with the naked eye or measure it with a relatively tight ruler, the lengths of A and B can never be equal, but in a certain respect, their lengths are equal, see the following picture:

      Make a triangle with straight line A and straight line B, assuming that there are two straight lines intersecting A and B, intersecting point mn and point m' n' in A and B respectively, we can see that we can find on straight line B Points corresponding to the points in A, so we can understand that the set of midpoints of line segment A is equal to the set of midpoints of line segment B, so we understand that the lengths of A and B are equal, so this is the mapping, presumably everyone has already With the most basic concept of mapping, let's explain what discretization is.

2. Scope of application : the number in the array is not very large, but the value is large

Example: [-1,2,50,1000]-->[0,1,2,3] This mapping process is discretization

Note : Generally, there are negative numbers or large values, we will use discretization

  • Negative numbers: Because the indexes in the array are non-negative, we cannot directly map the corresponding value to the index in the array, so we need to use discretization.
  • If the value is very large, adding a value of 100000, we can never create an array with a length of 100000, so we need to discretize

Discretization steps:

  1. Use an auxiliary array to store the data you need to discretize (copy the original array)
 //原数组 
 int[] nums={-9,5,-6,5,10000};
//辅助数组
 int[] aim= Arrays.copyOfRange(nums,0,nums.length);

      2. Sort and deduplicate the auxiliary array

//对原数组进行去重、排序,并生成一个新的数组c 
int [] c=Arrays.stream(aim).distinct().sorted().toArray();

General steps: 

 The method of binary search will share the code with you:

    // 二分查找法
    private int find(int[] arr, int num) {
        if(arr == null || arr.length == 0){ //数组为空
            return -1;
        }
        int left=0;
        int right=arr.length-1;
        // 先找中间值
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] == num) {
                return mid;
            } else if (arr[mid] > num) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return -1;
    }

 Second, the tree array

                       tree array binary tree

Advantages and disadvantages of tree arrays:

Advantages: The complexity of modification and query operations is the same as the line segment tree is logN, but the constant is smaller than the line segment tree, and the implementation is simpler than the line segment tree.

Disadvantages: weak scalability, the problem that the line segment tree can solve, the tree array may not be able to solve.

Note: Suppose we modify the value of node 5. In the tree array, we only need to modify the values ​​of nodes 6 and 8. How can we decide which nodes to modify after modifying a node? Come down and let's see together

 lowbit(x) operation:

 //二进制
    public int lowbit(int x){
        return x&(-x);
    }

 Here we first review how to calculate the original code, inverse code, and complement code of a number

Original code: The highest bit of a binary positive number is 0, the highest bit of a negative number is 1, and the highest bit is a sign bit

Inverse code: The inverse code of a positive number is the same as the original code. The inverse code of a negative number is unchanged except for the sign bit, and the other positions are reversed. 0-1 1-0

Complement code: The complement code of positive numbers is the same as the original code, and the complement code of negative numbers is equivalent to the inverse code of negative numbers + 1

Suppose the node we modify is 5

5+1=6   

6+2=8 

Therefore, the next + value can be obtained by continuously performing lowbit operations on the i value

   //树状数组进行添加元素
    public void add(int index,int val){
        for (int i = index; i <this.C.length; i+=lowbit(i)) {
             this.C[i]+=val;
        }
    }

 The same is true for forward push, and the same is true for reverse push (such as summation, a large interval is merged by many small intervals)

    //元素查询
    public int preSarch(int index){
        int sum=0;
        for (int i =index; i >0; i-=lowbit(i)) {
            sum+=this.C[i];
        }
        return sum;
    }

 If you want to modify:

 public void update(int index, int val) {
        //添加的val是差值量
       this.add(index+1,val-this.A[index]);
       //更改原数组中的值
       this.A[index]=val;
    }

 Tree array source code (template):

    //数组
    private int[] A;
    //树状数组
    private int[] C;
    //长度
    private int length;
     //二进制
    public int lowbit(int x){
        return x&(-x);
    }

    public NumArray(int[] nums) {
         this.A= Arrays.copyOfRange(nums,0,nums.length);
         this.C=new int[nums.length+1];
         this.length=nums.length;
         //构造树状数组,将原数组中的数添加到树状数组中
        for (int i = 0; i <this.length; i++) {
            this.add(i+1,this.A[i]);
        }
    }
    //树状数组进行添加元素
    public void add(int index,int val){
        for (int i = index; i <this.C.length; i+=lowbit(i)) {
             this.C[i]+=val;
        }
    }
    //元素查询
    public int preSarch(int index){
        int sum=0;
        for (int i =index; i >0; i-=lowbit(i)) {
            sum+=this.C[i];
        }
        return sum;
    }


    public void update(int index, int val) {
        //添加的val是差值量
       this.add(index+1,val-this.A[index]);
       //更改原数组中的值
       this.A[index]=val;
    }

    public int sumRange(int left, int right) {
     return preSarch(right+1)-preSarch(left);
    }

       Presumably everyone already has a general understanding of discretization and numerical arrays. I believe this knowledge can help you go further in the learning process of algorithms!!!

 

Guess you like

Origin blog.csdn.net/dfdbb6b/article/details/130964040