在音乐播放器中实现随机播放功能

时间:2014-06-30 16:53:33

标签: random

在接受采访时被问及

    "What is the most efficient way to implement a shuffle function in a music
     player to play random songs without repetition"

我建议使用链接列表方法,即使用链接列表,生成随机数并从列表中删除该项目/歌曲(这样,我们确保不会重复播放歌曲)

然后我提出了位向量方法但他并不满意。
那么根据你是实现这种功能的最佳方法呢?

3 个答案:

答案 0 :(得分:1)

没有完美的答案,我想这类问题的目的是开始讨论。很可能你的面试官想要了解Fisher–Yates shuffle (aka Knuth shuffle)

以下是wiki的简要介绍:

  
      
  1. 记下从1到N的数字。
  2.   
  3. 选择一个与剩余(包括)的未打击数字之间的随机数k。
  4.   
  5. 从低端计算,删除尚未击出的第k个数字,并将其写在别处。
  6.   
  7. 从步骤2开始重复,直到所有数字都被删除。
  8.   
  9. 在步骤3中记下的数字序列现在是原始数字的随机排列。
  10.   

你应该提到它的低效率和好处,你如何改进它,抛出几行代码并讨论你将如何以及如何测试这段代码。

答案 1 :(得分:0)

以下是一些实现。面试时我也遇到困难,但是面试后我发现解决方案很简单。

public class MusicTrackProgram {

// O(n)  in-place swapping
public static List<MusicTrack> shuffle3(List<MusicTrack> input) {

    Random random = new Random();

    int last = input.size() - 1;

    while (last >= 0) {

        int randomInt = Math.abs(random.nextInt() % input.size());

        // O(1)
        MusicTrack randomTrack = input.get(randomInt);

        MusicTrack temp = input.get(last);

        // O(1)
        input.set(last, randomTrack);
        input.set(randomInt, temp);

        --last;

    }

    return input;

}

// O(n)  but extra field
public static List<MusicTrack> shuffle(List<MusicTrack> input) {

    List<MusicTrack> result = new ArrayList<>();

    Random random = new Random();

    while (result.size() != input.size()) {

        int randomInt = Math.abs(random.nextInt() % input.size());

        // O(1)
        MusicTrack randomTrack = input.get(randomInt);

        if (randomTrack.isUsed) {
            continue;
        }

        // O(1)
        result.add(randomTrack);
        randomTrack.isUsed = true;

    }

    return result;

}

// very inefficient O(n^2)
public static List<MusicTrack> shuffle2(List<MusicTrack> input) {

    List<MusicTrack> result = new ArrayList<>();

    Random random = new Random();

    while (result.size() != input.size()) {

        int randomInt = Math.abs(random.nextInt() % input.size());

        // O(1)
        MusicTrack randomTrack = input.get(randomInt);

        // O(1)
        result.add(randomTrack);

        // O(n)
        input.remove(randomTrack);
    }

    return result;

}


public static void main(String[] args) {

    List<MusicTrack> musicTracks = MusicTrackFactory.generate(1000000);

    List<MusicTrack> result = shuffle3(musicTracks);

    result.stream().forEach(x -> System.out.println(x.getName()));
}

}

答案 2 :(得分:0)

我们可以使用链接列表和队列在mp3播放器中实现歌曲搜索 我们可以将其扩展到以下功能:

  1. 添加新歌
  2. 删除歌曲
  3. 随机播放一首歌曲
  4. 在播放队列中添加歌曲

假设最初我们有6首歌曲存储为链接列表 链接列表有2个指针:开始和结束

totalSongCount = 6

随机播放歌曲: 我们将生成一个介于1到totalSongCount之间的随机数。设为4 我们将删除代表歌曲4的节点并将其保留在结束指针之后 我们将减少totalSongCount(totalSongCount-)。

当我们减小totalSongCount时,下一次将在1-5之间生成随机数,我们可以重复该过程

要添加一首新歌,只需将其添加到链接列表并使其作为指针(添加在开头) 增加totalSongCount(totalSongCount ++)

要删除歌曲,请先找到并删除它 如果不只是减小totalSongCount(totalSongCount--),也要跟踪是否在结束指针之后。

所选歌曲可以有两个选项: 在那一刻玩 添加到播放列表(单独的队列)