【问题标题】:implementing shuffle functioning in a music player在音乐播放器中实现随机播放功能
【发布时间】:2022-05-06 20:12:35
【问题描述】:

这是在采访中被问到的

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

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

然后我建议使用位向量方法,但他一点也不满意。
那么您认为实现这种功能的最佳方法是什么?

【问题讨论】:

  • 我不确定最有效的解决方案是什么,但您可能应该从最明显的问题开始:随机列表。

标签: random


【解决方案1】:

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

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】:

没有完美的答案,我猜这类问题是为了引发讨论。很可能你的面试官想知道Fisher–Yates shuffle (aka Knuth shuffle)

这是来自 wiki 的简要概述:

  1. 写下从 1 到 N 的数字。
  2. 在 1 和剩余的未命中数(包括)之间选择一个随机数 k。
  3. 从低端数,剔除第k个尚未剔除的数字,并写在别处。
  4. 从第 2 步开始重复,直到所有数字都被删除。
  5. 步骤 3 中写下的数字序列现在是原始数字的随机排列。

您应该提及它的低效率和好处,如何改进它,输入几行代码并讨论您将测试此代码的内容和方式。

【讨论】:

    【解决方案3】:

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

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

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

    totalSongCount=6

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

    下一次将在 1 到 5 之间生成随机数,因为我们已经减少了 totalSongCount ,我们可以重复这个过程

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

    要删除一首歌,首先找到它并删除它 还要跟踪它是否在结束指针之后,如果它不只是减少 totalSongCount (totalSongCount--)

    所选歌曲可以有两个选项: 要么在那个时候玩,要么 添加到播放列表(单独队列)

    【讨论】:

      【解决方案4】:
      I think below solution should work 
      
      class InvalidInput extends Exception{
          public InvalidInput(String str){
              super(str);
          }
      }
      
      class SongShuffler{
      
          String songName[];
          int cooldownPeriod;
          Queue<String> queue;
          int lastIndex ;
          Random random;
      
          public SongShuffler(String arr[], int k) throws InvalidInput{
              if(arr.length < k)
                  throw new InvalidInput("Arr length should be greater than k");
              songName = arr;
              cooldownPeriod = k;
              queue = new LinkedList<String>();
              lastIndex = arr.length-1;
              random = new Random();
          }
      
          public String getSong(){
              if(queue.size() == cooldownPeriod){
                  String s = queue.poll();
                  songName[lastIndex+1] = s;
                  lastIndex++;
              }
              int ind = random.nextInt(lastIndex);
              String ans = songName[ind];
              queue.add(ans);
              songName[ind] = songName[lastIndex];
              lastIndex--;
              return ans;
          }
      
      }
      

      【讨论】:

      • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-03
      相关资源
      最近更新 更多