fish-yates算法

由于最近老是隔三岔五地要写一些随机打乱字符的任务,每次首选都是fisher-yates算法,但是傻子风脑子不太灵光,老是忘记流程,遂记此博客作为记忆存档

算法简述

Fisher-Yates 洗牌算法 是一种用于生成有限序列的无偏随机排列的算法。简单说,它能真正做到等概率地随机打乱一个数组。

核心思想(现代版本,由 Knuth 提出):
从数组末尾开始,向前遍历。对于当前最后一个元素(索引 i),随机地从前面未固定的部分(包括它自己)选择一个元素(索引 j),并交换它们的位置。通过这种方式,每个元素在迭代过程中都有一次机会被放置到当前序列的“末尾”,这个“末尾”在后续的遍历中将被固定下来,不再改动。

算法步骤:

  1. 设当前索引 i 为数组的最后一个元素的索引(arr.length - 1)。
  2. 当 i > 0 时,循环:
    a. 生成随机索引 j:范围在 [0, i](包括 0 和 i)之间的一个随机整数。
    b. 交换元素:交换数组中索引为 i 和索引为 j 的两个元素。
    c. 缩小范围:将 i 减 1,缩小随机选择的范围。
  3. 当循环结束(i == 0),数组已被完全随机打乱。

为什么它是无偏的?
因为每个元素在每次迭代中,被放置到当前“末尾”位置的概率都是完全相等的(1 / (i+1))。这保证了总共 n! 种可能的排列结果,每一种出现的概率都相同。

(以上由deepseek回答)

于此,我推荐B站上一位up主的一期视频对此算法有较为详尽的介绍,不过演示的是js,无伤大雅吧

【面试题】经典洗牌算法JS实现;Fisher-Yates算法;数组随机算法_哔哩哔哩_bilibili

以下,由于鄙人最近在用java写任务,就顺带附加一个java实现此算法的例子吧

import java.util.Random;//导包

public class Test {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7,8,9,10};
        Random r = new Random();
        int temp;//定义临时变量
        for (int i = arr.length - 1; i > 0; i--) {//写一个循环用于打乱数组
            int index = r.nextInt(i + 1);
            temp = arr[i];
            arr[i] = arr[index];
            arr[index] = temp;
        }

        //输出数组查看打乱效果
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
    
}

评论

  1. 夜屿
    5 月前
    2025-9-11 6:48:56

    ヾ(≧∇≦*)ゝ

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇
皖ICP备2025092305号-1