有人问我这个问题,在接受采访时,我给了不同的解决方案,但面试官没有被说服。我有兴趣找到一个解决方案。请扔在你的意见:

问:写一个有效的数据结构来实现在一个iPod洗牌。它必须发挥所有的歌曲,在不同的随机顺序每一次,同一首歌不应该被重复。 (主要是O(n))的

一个解决方案,我想离开面试后:我可以做一个随机快速排序没有递归。当我们随机,选择1支点O(1),然后做快速排序为O(n)。现在的歌曲会以某种顺序进行排序和我玩他们,直到结束。一旦它到达终点,我会再次选择一个随机的支点,并一次又一次地重复这一过程。

此致 Sethu

有帮助吗?

解决方案

将所有的在阵列中的歌曲... 对于与一个随机位置阵列交换它的每个元素。

其他提示

您想费雪耶茨洗牌。要知道,网页上提到的实施错误的,因为你目前公认的答案落在犯规之一。

那么,第一个线性时间的解决方案,弹簧想到:

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

对于每个为O(n)+为每个为O(n)的移除+第二插入为O(n)的插入。这会整体导致一个线性时间的解决方案。

修改:我完全忘记行走列表。所以,相反,你可以使结果一个固定长度的数组。弹出链接列表的头部,它分配所述随机索引,并填充阵列。

Nate的(编辑)和Brian的算法是费希尔 - 耶茨洗牌为O(n),而由混洗排序是O(nlogn),但实际上可以是在实践中更快(http://en.wikipedia.org/wiki /费舍尔%E2%80%93Yates_shuffle#Comparison_with_other_shuffling_algorithms)。获取歌曲洗牌错误可能有显着影响,但如果你是一个在线扑克游戏编写一个洗牌的算法,确保你知道你在做什么(http://www.cigital.com/news/index.php?pg=艺术&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 */

工作原理是它将整个数组作为帽子,并开始拉动随机元素和衬起来在阵列的前部。 i后所有的元素都是“在桶”,i之前的所有元素进行混洗。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top