随机化数组的有效方法 - Shuffle 代码

发布于 2024-09-29 14:25:40 字数 288 浏览 0 评论 0原文

我在面试中被问到这个问题,我给出了各种解决方案,但面试官并不相信。我有兴趣找到解决方案。请提出您的看法:

问:编写一个高效的数据结构来实现ipod中的shuffle。它必须播放所有歌曲,每次以不同的随机顺序播放,同一首歌曲不应重复。 (主要是 O(n))

一个解决方案,我在面试后想到:我可以进行随机快速排序而不需要递归。我们随机选择 1 个主元 O(1),然后进行快速排序 O(n)。现在歌曲将按某种顺序排序,我会一直播放到最后。一旦到达终点,我将再次选择一个随机枢轴,并一次又一次地重复这个过程。

问候, 塞图

I was asked this question in an interview and I gave various solutions but the interviewer was not convinced. I am interested to find a solution. Please throw in your views :

Q: Write an efficient data structure to implement the shuffle in an ipod. It must play all the songs, each time in different random order, the same song should not be repeated. ( mostly O(n))

One solution , I thought off after the interview : I can do a randomized quick sort without recursion. Where we randomly, chose 1 pivot O(1) and then do quicksort O(n). Now songs will be sorted in some order and I play them till the end. Once it reaches the end, I will Again chose a random pivot and , repeat this process again and again.

Regards,
Sethu

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

几味少女 2024-10-06 14:25:41

您需要 Fisher-Yates 洗牌。请注意该页面上提到的实施错误,因为您当前接受的答案不符合其中之一。

You want the Fisher-Yates shuffle. Be aware of the implementation errors mentioned on that page, as your currently accepted answer falls foul of one.

不甘平庸 2024-10-06 14:25:41

将所有歌曲放入一个数组中...
对于数组中的每个元素,将其与随机位置交换。

Place all the songs in an array...
For each element in the array swap it with a random position.

冷清清 2024-10-06 14:25:41

好吧,我想到的第一个线性时间解决方案是:

您可以创建所有歌曲的链接列表,这大约需要 O(n) (假设插入是常数时间操作)。然后,生成一个随机数,对列表的大小取模以获得随机索引,然后删除该索引并将其附加到新列表(两者都是恒定时间操作)。

每个 O(n) 的插入 + 每个 O(n) 的删除 + 第二次插入 O(n)。这总体上会导致线性时间解决方案。

编辑:我完全忘记了要遍历列表。因此,您可以将结果设为固定长度数组。弹出链表的头部,为其分配随机索引,然后填充数组。

Well, the first linear-time solution that springs to mind:

You could make a linked list of all the songs, which would take about O(n) (given that insertions are constant time operations). Then, generate a random number, modulo the size of the list to get a random index, and remove that index and append it to a new list (both of which are constant time operations).

An insertion for each O(n) + a removal for each O(n) + a second insertion O(n). This would overall lead to a linear time solution.

Edit: I completely forgot about walking the list. So, instead, you could make the result a fixed length array. Pop the head of the linked list, assign it the random index, and populate the array.

兔姬 2024-10-06 14:25:41

Nate(编辑)和 Brian 的算法是 Fisher–Yates 洗牌 O(n),而通过排序洗牌是 O(nlogn),但实际上在实践中可能更快 (http://en.wikipedia.org/wiki/Fisher% E2%80%93Yates_shuffle#Comparison_with_other_shuffling_algorithms)。歌曲洗牌错误可能会产生微不足道的后果,但如果您正在为在线扑克游戏编写洗牌算法,请确保您知道自己在做什么 (http://www.cigital.com/news/index.php?pg=艺术&艺术= 20)。

Nate's (edited) and Brian's algorithms are the Fisher–Yates shuffle O(n), while shuffling by sorting is O(nlogn), but may actually be faster in practice (http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Comparison_with_other_shuffling_algorithms). Getting song shuffling wrong may have insignificant consequences, but if you are writing a shuffling algorithm for an online poker game, make sure you know what you are doing (http://www.cigital.com/news/index.php?pg=art&artid=20).

情感失落者 2024-10-06 14:25:41

您想要的是 Fisher-Yates Shuffle。下面是 java 中的一个实现:

public void shuffle(Song[] songs) {
    Random r = new Random();
    for(int i = 0; i < songs.length - 1; i++) {
        int swap = i + r.nextInt(songs.length-1-i);
        T temp = songs[i];
        songs[i] = songs[swap];
        songs[swap] = temp;
    }
}
/* r.nextInt(max) returns integer 0 to max-1 inclusive */

它的工作原理是将整个数组视为一顶帽子,并开始提取随机元素并将它们排列在数组的前面。 i 之后的所有元素都“在桶中”,i 之前的所有元素都被打乱。

What you want is the Fisher-Yates Shuffle. Here's an implementation in java:

public void shuffle(Song[] songs) {
    Random r = new Random();
    for(int i = 0; i < songs.length - 1; i++) {
        int swap = i + r.nextInt(songs.length-1-i);
        T temp = songs[i];
        songs[i] = songs[swap];
        songs[swap] = temp;
    }
}
/* r.nextInt(max) returns integer 0 to max-1 inclusive */

How it works is it treats the entire array as a hat and starts pulling random elements and lining them up at the front of the array. All elements after i are 'in the bucket', all elements before i are shuffled.

ζ澈沫 2024-10-06 14:25:41

我是初学者,说一个我想到的解决方案,如果有问题请告诉我。

假设歌曲存储在单链表或双链表中。每次打开音乐播放器时,选择一个小于(您想要的任何数字)假设 k 的随机数,并反转列表中的每个 k 节点,类似地执行两次或最多三次(如您所愿),这将需要 O( 2n) 或 O(3n) 时间进行洗牌。
最后有一个指向链表最后一个节点的指针。
每次听一首歌曲(访问一个节点)时,都会删除该节点并将其插入到最后一个节点旁边,这可以在 O(1) 时间内完成。
这将持续到音乐播放器关闭为止。

谢谢,
渴望知道答案的正确性。

I am a beginner, let me say a solution that strikes to mind, if anything is wrong please make me know.

Lets assume songs are stored in either singly or doubly linked list. Every time when the music player is opened pick a random number less than (any number you wish) assume k, and reverse every k nodes in the list, similarly do it twice or at max thrice (as you wish) which would take O(2n) or O(3n) time to shuffle.
finally have a pointer to the last node of the list.
And every time a song is listened (a node is visited) remove the node and insert it next to the last node which can be done in O(1) time.
This continues till the music player is closed.

Thanks,
Eager to know the correctness of the answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文