Data structures 一种有效的数组随机码随机化方法

Data structures 一种有效的数组随机码随机化方法,data-structures,random,performance,memory-efficient,Data Structures,Random,Performance,Memory Efficient,我在一次面试中被问到这个问题,我给出了各种各样的解决方案,但面试官并不信服。我有兴趣找到解决办法。请提出你的看法: Q:编写一个高效的数据结构,在ipod中实现洗牌。它必须播放所有歌曲,每次以不同的随机顺序播放,同一首歌曲不应重复。(主要是O(n)) 一个解决方案,我在面试后想:我可以做一个随机快速排序,而不需要递归。在这里,我们随机选择1个枢轴O(1),然后进行快速排序O(n)。现在歌曲将按一定顺序排序,我将播放到最后。一旦到达终点,我将再次选择一个随机轴,并一次又一次地重复这个过程 问候,,

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

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

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

问候,,
Sethu

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

首先想到的是线性时间解决方案:

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

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


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

Nate(已编辑)和Brian的算法是Fisher–Yates shuffle 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=art&artid=20).

你想要这个。请注意该页面上提到的实现错误,因为您当前接受的答案与其中一个不符

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

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

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

你想要的是答案。下面是一个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 */
public void shuffle(歌曲[]歌曲){
随机r=新随机();
for(int i=0;i

它的工作原理是将整个阵列视为一顶帽子,开始拉动随机元素并将它们排列在阵列的前面。
i
之后的所有元素都“在桶中”,而
i
之前的所有元素都被洗牌。

与我的建议基本相同。使用C#列表,您可以得到
RemoveAt
,它可以为您进行删除和收缩(不适用于iPod,但…)删除链接列表中某个索引处的元素不是固定时间。一个元素的实际移除(意味着仅仅移除指向它的指针并释放内存)是O(1),但是因为您首先需要导航到该元素,所以在最坏的情况下是O(n)。在这里,我们应该确保我们选择的随机数不会重复。我碰到了同样的问题,你有什么解决办法吗?但在这种情况下,歌曲被重复的几率很高,对吧?@sethu:如果你交换它,就不会了。如将ABCD更改为CBAD。每次交换只是将其更改为原始元素的不同排列。这是不正确的。这不会产生随机排列。这个错误很常见,在维基百科上有描述:@Dijkstra:Hats off!你说得对。尽管在这个应用程序中,这可能并不重要。