Loading

算法和数据结构学习中的一些小的工具函数

算法和数据结构学习中的一些小的工具函数

作者:Grey

原文地址:

博客园:算法和数据结构学习中的一些小的工具函数

CSDN:算法和数据结构学习中的一些小的工具函数

提取一个数二进制最右侧的 1

比如二进制为:0100 0001 0001 1011 0001 0001 1001 1000

最右侧的1为: 0000 0000 0000 0000 0000 0000 0000 1000

提取公式为:

num & (-num)

num & (~num + 1)

打印一个 32 位整数的二进制形式

public static String getBinary(int num) {
    StringBuilder sb = new StringBuilder();
    for (int i = 31; i >= 0; i--) {
        sb.append(((1 << i) & num) == 0 ? "0" : "1");
    }
    return sb.toString();
}

前缀和数组加速求区间和

在数组不可变的情况下,可以使用前缀和数组加速求区间和,描述见:leetcode 0303 range sum query immutable

    static class NumArray {
        int[] preSum;

        public NumArray(int[] nums) {
            // 0 位置弃而不用
            // 在判断 rangeSum 的时候可以省去一个 if
            preSum = new int[nums.length + 1];
            for (int i = 1; i < preSum.length; i++) {
                preSum[i] = nums[i - 1] + preSum[i - 1];
            }
        }

        // preSum 1 = nums 0 + preSum 0
        // preSum 2 = nums 1 + preSum 1
        // preSum 3 = nums 2 + preSum 2
        // preSum 4 = nums 3 + preSum 3
        //      0 1 2 3
        // nums 1 2 3 4
        // pres 0 1 3 6 10
        public int sumRange(int left, int right) {
            // 1 ~ 2 => preSum 3 - preSum 1 => nums 2 + nums 1 + nums 0 - nums 0
            return preSum[right + 1] - preSum[left];
        }
    }

注:前缀和只适合数组不可变情况下加速求区间和,如果数组可变,则需要使用线段树或者树状数组来解决这个问题。

要表示 0 ~ range 这个区间的所有数字,需要几个二进制位

public static int getNeedBits(int range) {
    int num = 1;
    while ((1 << num) - 1 < range) {
        num++;
    }
    return num;
}

思路也很简单,(1 << num) - 1 表示 num 个二进制位可以表示的最大数是多少,比如 num = 3
(1 << num) - 1 的二进制表示就是111, num = 4(1 << num) - 1 的二进制表示就是1111,

如果 range 大于这个二进制值,则 num 个二进制位一定表示不了,则 num++

[0,x)中的数出现的概率调整成\(x^2\)

public static double randToPow2() {
    return Math.max(Math.random(), Math.random());
}

说明:在 Java 语言中,Math.random()表示的是[0,1)区间中任意一个数 x 的出现的概率是 x,因为上述函数返回的结果要在[0,1)区间内,且我们使用的是Math.max方法,则两次调用Math.random()方法都要满足在[0,1)区间内才能符合要求,所以概率是\(x^2\)

可以用下述方法进行测试

public class Code_RandToPow2 {
    // 将`[0,x)`中的数出现的概率调整成 x^2
    public static double randToPow2() {
        return Math.max(Math.random(), Math.random());
    }

    // 测试用例
    public static void main(String[] args) {
        int count = 0;
        int testTimes = 40000000;
        double x = 0.18;
        for (int i = 0; i < testTimes; i++) {
            if (randToPow2() < x) {
                count++;
            }
        }
        // 以下两个数值应该大小接近一致
        System.out.println((double) count / (double) testTimes);
        System.out.println(Math.pow(x, 2));
    }
}

运行,可以得到结果对比

0.032397025
0.0324

更多随机函数的变换技巧见:随机函数变换相关技巧

持续更新中

更多

算法和数据结构学习笔记

算法和数据结构学习代码

posted @ 2023-09-05 10:23  Grey Zeng  阅读(51)  评论(0编辑  收藏  举报