蓄水池抽样算法 leetcode 398 382



 

 

382 https://leetcode-cn.com/problems/linked-list-random-node/submissions/

复制代码
//只抽取一个元素,使得这个元素是等可能的
   int getRandom1(ListNode head){
        Random r = new Random();
        int i = 0;
        int result= 0;
        ListNode p = head;
        while(p!=null){
            i++;
            if(r.nextInt(i) == 0){// 咋 [0,i) 之间的 等于0的概率为 1/i 这样就能保证所有的元素最后的概率为 1/n
                result = p.val;
            }
            p = p.next;
        }
        return result;
    }
复制代码

  

398等概率的找到target   https://leetcode-cn.com/problems/random-pick-index/submissions/

复制代码
class Solution {
    private int[] nums;
    private Random random = new Random();
    public Solution(int[] nums) {
        this.nums = nums;
    }
    
    public int pick(int target) {
        int result = 0;
        int k = 0;
        for(int i = 0; i< nums.length; i++){
            //先找到满足条件的元素
            if(nums[i] == target){
                //k表示nums中等于target的数字个数
                //需要保证这个数字被选择的概率是  1/k;
                //那就需要使用在   在[0,k)之间选择数字 使得 概率为 1/k
                k++;
                if(random.nextInt(k) == 0){
                    //在[0,k)之间选择数字 使得 概率为 1/k
                    //每次以1/k的概率更新结果
                    result = i;
                }
            }
        }
        return result;
    }
}

/**
 * Your Solution object will be instantiated and called as such:
 * Solution obj = new Solution(nums);
 * int param_1 = obj.pick(target);
 */
复制代码

 

泛化--- 未知长度,k个元素 等可能

需要随机选择 k 个数, 保证每个都是等可能的,只能遍历一次

复制代码
    //抽取k个元素,使得k个元素是等可能的 在这个k个元素中任意一个i 的概率为 k/n
    //只要保证任意的在 被选择的时候 保证 概率为 k/i就行
    int[] getRandomk(ListNode head,int k){
       Random r = new Random();
       int[] result = new int[k];
       ListNode p = head;
       //step1: 先找到符合要求的元素 k个
       //先将前面k个元素先选上
       for (int i = 0; i < k && p!=null; i++) {
            result[i] = p.val;
            p = p.next;
        }
       int i = k;
       //step2: 保证概率
       while(p!= null){
           i++;
           //随机生成一个随机数
           int j = r.nextInt(i);//先随机生成一个[0,i)之间的数 j
           if(j < k){//如果j 在 k 的范围内,则概率等可能的 概率 为 k/i 则可以替换
               result[j] = p.val;//将做的新的选择 替换到result中
           }
           p = p.next;
       }
       return result;
    }
复制代码

 

 

---

复制代码
import java.util.Random;

/**
 * @ClassName GetRandom
 * @Description TODO
 * @Author Administrator
 * @Date 2022/4/8 10:03
 * @Version 1.0
 **/
public class GetRandom {
    //只抽取一个元素,使得这个元素是等可能的
   int getRandom1(ListNode head){
        Random r = new Random();
        int i = 0;
        int result= 0;
        ListNode p = head;
        while(p!=null){
            i++;
            if(r.nextInt(i) == 0){
                result = p.val;
            }
            p = p.next;
        }
        return result;
    }
    //抽取k个元素,使得k个元素是等可能的 在这个k个元素中任意一个i 的概率为 k/n
    //只要保证任意的在 被选择的时候 保证 概率为 k/i就行
    int[] getRandomk(ListNode head,int k){
       Random r = new Random();
       int[] result = new int[k];
       ListNode p = head;
       //step1: 先找到符合要求的元素 k个
       //先将前面k个元素先选上
       for (int i = 0; i < k && p!=null; i++) {
            result[i] = p.val;
            p = p.next;
        }
       int i = k;
       //step2: 保证概率
       while(p!= null){
           i++;
           //随机生成一个随机数
           int j = r.nextInt(i);//先随机生成一个[0,i)之间的数 j
           if(j < k){//如果j 在 k 的范围内,则概率等可能的 概率 为 k/i 则可以替换
               result[j] = p.val;//将做的新的选择 替换到result中
           }
           p = p.next;
       }
       return result;
    }

}
复制代码

 

posted @   zhongweiLeex  阅读(64)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示