028、带权重的随机选择算法(labuladong)

该算法通过将权重数组转换为前缀和数组,然后使用二分搜索在随机生成的数值内找到对应权重的索引。在随机数位于[1,preSum[n-1]]的闭区间内,返回的left值表示目标元素在数组中的插入位置或大于等于目标的最小元素索引。
摘要由CSDN通过智能技术生成

带权重的随机选择算法

基于labuladong的算法网站,带权重的随机选择算法

1、概述

在这里插入图片描述

2、解题思路

前缀和+二分搜索:

  • 将权重数组变成前缀和数组;
  • 生成一个在权重数组内的随机数,随机数落在权重数组区间的概率,即为最终答案;
    在这里插入图片描述

3、解法代码

重点:

  • 开闭区间:左开右闭;
[528]按权重随机选择

class Solution {
    private Random random = new Random();
    private int[] preSum;
    private int n;

    public Solution(int[] w) {
        this.n = w.length;
        // 前缀数组,下标0就是原数组w[0]
        preSum = new int[n];
        // 下标0就是原数组w[0]
        preSum[0] = w[0];
        for (int i = 1; i < n; i++) {
            preSum[i] = preSum[i-1] + w[i];
        }
    }

    public int pickIndex() {
        // 保证取到[1, preSum[n-1]]的闭区间
        int target = random.nextInt(preSum[n-1]) + 1;
        // right可以从n-1开始,也可以从n开始,对结果的正确性没有影响
        int left = 0, right = n;
        while (left < right) {
            int mid = left + (right - left) / 2;
            // 如果找到了,直接去当前的下标
            if (preSum[mid] == target) {
                left =mid;
                break;
            } else if (preSum[mid] > target) {
                // 向左找,因为当前mid的值大于target,可能是"第一个大于target"的值,所以不能丢弃mid
                // 如果mid的值不再需要了(最终不会取到现在的mid),那么就可以right=mid-1;
                right = mid;
            } else {
                // 向右找,因为当前的mid的值比target小,永远不会取到了。所以left=mid+1;
                left = mid + 1;
            }
        }
        // left代表的含义:
        // 当目标元素 target 不存在数组 nums 中时,搜索左侧边界的二分搜索的返回值可以做以下几种解读:
        // 1、返回的这个值是 nums 中大于等于 target 的最小元素索引。
        // 2、返回的这个值是 target 应该插入在 nums 中的索引位置。
        // 3、返回的这个值是 nums 中小于 target 的元素个数。
        return left;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C#中,权重随机选择通常涉及到概率分布和随机数生成。一个常见的方法是使用`System.Collections.Generic.Dictionary<TKey, TValue>`或者`Dictionary<T, double>`来存储元素及其对应的权重,然后利用这些权重来计算每个元素被选中的概率。这里有一个简单的概念实现: ```csharp using System; using System.Collections.Generic; using System.Linq; class WeightedRandomSelection { private readonly Dictionary<int, double> weights; public WeightedRandomSelection(Dictionary<int, double> weights) { this.weights = weights; // 确保所有权重的和为1(或接近于1),以便进行正确的概率计算 double totalWeight = weights.Values.Sum(); if (totalWeight != 1) { weights = weights.ToDictionary(kvp => kvp.Key, kvp => kvp.Value / totalWeight); } } public int Choose() { double randomValue = Random.NextDouble(); // 0到1之间的随机浮点数 double cumulativeProbability = 0; foreach (var (key, weight) in weights) { cumulativeProbability += weight; if (randomValue <= cumulativeProbability) { return key; } } throw new InvalidOperationException("无法生成随机选择,可能是因为权重总和不为1"); } } public class Program { static void Main(string[] args) { Dictionary<int, double> selections = new Dictionary<int, double> { {1, 0.3}, {2, 0.4}, {3, 0.3} }; WeightedRandomSelection random = new WeightedRandomSelection(selections); int chosenNumber = random.Choose(); Console.WriteLine($"随机选择了数字: {chosenNumber}"); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值