首页 > 编程语言 >算法:给定 n 个不同元素的数组,设计算法等概率取 m 个不同的元素

算法:给定 n 个不同元素的数组,设计算法等概率取 m 个不同的元素

时间:2023-06-27 21:44:05浏览次数:39  
标签:int 元素 算法 给定 result 数组 array

 

 

有几种算法可以实现从n个不同元素的数组中等概率地取出m个不同元素,

其中一种是Knuth-Durstenfeld Shuffle算法,它的思想是:

  • 将1到n的数字存到数组中
  • 从数组中取一个1到剩下数字个数的随机数k
  • 从低位开始,将数组第k个数字取出,并保存到结果数组末尾
  • 重复第2步,直到取出m个数字

这种算法的时间复杂度是O (n),空间复杂度是O (m)。

用Java语言实现的话,可以参考以下代码:

import java.util.Random;

public class RandomSelect {

    // 从n个不同元素的数组中等概率地取出m个不同元素
    public static int[] select(int[] array, int m) {
        int n = array.length;
        if (m > n) {
            throw new IllegalArgumentException("m cannot be larger than n");
        }
        int[] result = new int[m]; // 存放结果的数组
        Random random = new Random(); // 随机数生成器
        for (int i = 0; i < m; i++) {
            int k = random.nextInt(n - i) + i; // 生成一个i到n-1之间的随机数
            result[i] = array[k]; // 将第k个元素放入结果数组
            swap(array, i, k); // 将第k个元素与第i个元素交换,保证已选中的元素不会再被选中
        }
        return result;
    }

    // 交换数组中两个位置的元素
    public static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9}; // 测试数组
        int m = 4; // 要取出的元素个数
        int[] result = select(array, m); // 调用算法
        for (int num : result) { // 打印结果
            System.out.print(num + " ");
        }
    }
}

这种算法有什么优缺点?

Knuth-Durstenfeld Shuffle算法的优点

  • 是它的时间复杂度和空间复杂度都很低,只需要O (n)的时间和O (1)的空间,
  • 而且能保证每个元素出现在每个位置上的概率相等。

它的缺点

  • 是它是一个in-place算法,会改变原始数据的顺序,而有些场景中我们需要保留原始数据。
  • 另外,它依赖于随机数生成器的质量,如果随机数生成器不够均匀或者有偏差,那么洗牌的结果也会受到影响。



标签:int,元素,算法,给定,result,数组,array
From: https://www.cnblogs.com/shoshana-kong/p/17509998.html

相关文章

  • 算法
    枚举 前缀和,差分前缀和:sum[i]=a[i]+sum[i-1] 前i个数的求和。差分:delta[i]=a[i]-a[i-1]第i个数-第i-1个数。例题:https://ac.nowcoder.com/acm/problem/166491#include<bits/stdc++.h>2usingnamespacestd;3/**4对于......
  • 垃圾回收与算法
    如何确定垃圾1、引用计数法:在Java中,引用和对象是有关联的,如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用,即他们的引用计数都不为0,则说明对象不太可能再被用到,那么这个对象就是可......
  • 如何获取页面上某个元素的坐标
    打开浏览器的F12控制台,在console内输入下面代码functiongetPosition(node){//获取元素相对于其父元素的left值varleftvarleft=node.offsetLeft;vartop=node.offsetTop;//取得元素的offsetParentcurrent=node.offsetParent;//一直循环直到根元素while(current!=nu......
  • 自动驾驶横纵向耦合控制-复现Apollo横纵向控制 基于动力学误差模型,使用mpc算法,一个控
    自动驾驶横纵向耦合控制-复现Apollo横纵向控制基于动力学误差模型,使用mpc算法,一个控制器同时控制横向和纵向,实现横纵向耦合控制matlab与simulink联合仿真,纵向控制已经做好油门刹车标定表,跟踪五次多项式换道轨迹,效果完美。内含三套代码,两套采用面向对象编程-一套只对控制量添加约......
  • re | 逆向算法笔记
    凯撒算法加密for(i=0;i<strlen(passwd);i++){if(passwd[i]>='A'&&passwd[i]<='Z'){passwd[i]=((passwd[i]-'A')+move)%26+'A';}elseif(passwd[i]>='a'&&......
  • CSS实现根据子元素数量应用不同样式
    在前端的页面布局中经常会出现在子元素个数使用不同的样式的需求,比如文章列表,在较少内容下单列表现,而在元素内容较多时使用双列表现。再比如在页面排版上,可以根据元素内容的多少来修改内容的缩放,位置,颜色等样式:has()选择器简介:has()选择器中的括号传递一个选择器参数,如果选......
  • Java求和元素_实现一个List集合中的某个元素的求和
    Listuserlist=userService.findAll();Integersum=userlist.stream().collect(Collectors.summingInt(User::getAge));packagecom.example.list_test;importjava.util.ArrayList;importjava.util.List;/***描述:ListTest3**@author何志鹏*@ClassName......
  • Prim算法 最小值生成树
    前言:给定一个无向图,如果它的某个子图中任意两个顶点都互相连通并且是一棵树,那么这棵树就叫做生成树(SpanningTree)。如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,MinimumSpanningTree)。例如我们假设有这样一个图:把顶点看作村庄,边看作计划要修建的道路。......
  • 操控元素常用方法
    WebElement 中的常用方法(1)clear():清除文本(2)send_keys(value):模拟按键输入(3)size:返回元素的尺寸(4)text:获取元素的文本(5)is_displayed():设置该元素是否用户可见(6)click():单击元素(7)submit():提交表单(8)get_attribute('class'):获取元素属性(9)quit():关闭浏览器element=wd.find_e......
  • 【算法】根据整数数组,生成正的素因子二位数组,并排序
    给定一个正整数或负整数的数组,I=[i1,..,in] 生成一个形式为的排序数组P [[p,I数组的所有ij的和,其中p是ij的素因子(p为正)]…]P将按素数的递增顺序进行排序。 示例:I={12,15};//结果=“(212)(327)(515)”[2,3,5]是I的元素的所有素因子的列表,因此是结果。 注意事项: 如果某些数字为......