27、随机算法

内容来自刘宇波老师算法与数据结构体系课

1、随机算法的简单分类

image
image
image
image
image
image

2、最基础的公平随机取样

image

398 - 随机数索引

public class Pick {

    private final Map<Integer, ArrayList<Integer>> map;
    private final Random random;

    public Pick(int[] nums) {
        random = new Random();
        map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int key = nums[i];
            if (!map.containsKey(key)) map.put(key, new ArrayList<>());
            map.get(key).add(i);
        }
    }

    public int pick(int target) {
        ArrayList<Integer> list = map.get(target);
        int size = list.size();
        // return list.get(random.nextInt(size));
        return list.get((int) (random.nextDouble() * size));
    }
}

3、加权随机取样

image
image
image
image

528 - 按权重随机选择

public class PickIndex {

    private final int[] presum;
    private final int sum;
    private final Random random;

    public PickIndex(int[] w) {
        // w[i] 代表第 i 个任务的权重, 也就是说, 应该给第 i 个任务发放 w[i] 张彩票
        // 给每个任务发放彩票, 总共发了 sum(w[]) 张彩票
        // 我们只需要记录每个任务的彩票区间就好了, 更近一步, 只需要记录每个任务第一张彩票的编号
        // 因为下一个任务第一张彩票的编号 = 上一个任务最后一张彩票的编号 + 1
        // presum[i] = 第 i 个任务第一张彩票的编号
        presum = new int[w.length];
        for (int i = 1; i < presum.length; i++) presum[i] = presum[i - 1] + w[i - 1];
        sum = presum[w.length - 1] + w[w.length - 1];

        random = new Random();
    }

    public int pickIndex() {
        int x = random.nextInt(sum);

        // 二分查找 presum[i] <= x 的最大值对应的 i
        int l = 0;
        int r = presum.length - 1;
        int mid;
        while (l < r) {
            mid = l + (r - l + 1) / 2;
            if (presum[mid] <= x) l = mid;
            else r = mid - 1;
        }

        return l;
    }
}

4、生成任意区间随机数

image

497 - 非重叠矩形中的随机点

// 作业

5、拒绝采样

image

6、使用 rand7,实现 rand10

image
image

470 - 用 Rand7() 实现 Rand10()

public class Rand10 {

    /**
     * 1 ~ 7
     */
    public int rand7() {
        return new Random().nextInt(7) + 1;
    }

    /**
     * 1 ~ 10
     */
    public int rand10() {
        while (true) {
            int a = rand7() - 1; // a in 0 ~ 6
            int b = rand7() - 1; // b in 0 ~ 6
            int t = a * 7 + b;   // t in 0 ~ 48
            if (t >= 40) continue;
            return t % 10 + 1;
        }
    }
}

478 - 在圆内随机生成点

// 作业

7、多次采样和洗牌算法

image
image
image
image
image

8、KnuthShuffle

image
image
image

384 - 打乱数组

public class KnuthShuffle {

    private final int[] nums;
    private final Random random;

    public KnuthShuffle(int[] nums) {
        this.nums = nums.clone();
        random = new Random();
    }

    public int[] reset() {
        return nums.clone();
    }

    /**
     * 从后向前决定排列中的每个元素
     */
    public int[] shuffle1() {
        int[] data = nums.clone();
        for (int i = data.length - 1; i >= 0; i--) {
            int j = random.nextInt(i + 1);
            swap(data, i, j);
        }
        return data;
    }

    /**
     * 从前向后决定排列中的每个元素
     */
    public int[] shuffle2() {
        int[] data = nums.clone();
        for (int i = 0; i < data.length; i++) {
            // random[i ... data.length - 1] = random[0 ... data.length - 1 - i] + i
            int j = random.nextInt(data.length - i) + i;
            swap(data, i, j);
        }
        return data;
    }

    private void swap(int[] arr, int a, int b) {
        int k = arr[a];
        arr[a] = arr[b];
        arr[b] = k;
    }
}

9、蓄水池抽样

image
image
image
image
image

382 - 链表随机节点

// 这个题目的接口不是很好
// Solution(int k)
// void fetch(int newValue)
// int[] sampling()

public class GetRandom {

    private final ListNode head;
    private final Random random;

    public GetRandom(ListNode head) {
        this.head = head;
        random = new Random();
    }

    /**
     * 蓄水池抽样, 蓄水池的大小为 1
     */
    public int getRandom() {
        int res = head.val;
        int index = 1;
        for (ListNode cur = head.next; cur != null; cur = cur.next, index++) {
            int j = random.nextInt(index + 1);
            if (j == 0) res = cur.val;
        }
        return res;
    }
}

10、随机采样算法小节

image

posted @ 2023-04-19 16:06  lidongdongdong~  阅读(23)  评论(0编辑  收藏  举报