【问题标题】:Shuffling of an array数组的洗牌
【发布时间】:2014-07-08 19:30:51
【问题描述】:

我已经写了一个洗牌字符串数组的方法所以任务是实现WhiteElephant概念(所有参与者的名字都被放入一个容器(帽子,盒子,包等)并混合在一起。每个然后该人从容器中选择一个名字,但没有告诉任何人选择了哪个名字。他/她现在负责为选定的人购买礼物。) 对于给定的名称列表字符串数组。应该生成分配以匹配原始元素。我已经编写了选择随机数的方法并使用映射来存储值,以便每个数组值都有不同的索引。但这仅打印出 5 个值。我现在很困惑。 ** 一个人必须分配给另一个人;不得将任何人分配给他/她自己。

public static String[] generateAssignments(final String[] participants) {

   Random r = new Random();
   int size = participants.length;
   HashMap val = new HashMap();
   int change = 0;
   String[] assignments = new String[6];
   System.out.println("Using arrays");


   for(int i=0; i<size;i++) {
       for(int j =0; j<size; j++) {
           change = r.nextInt(size);
           if(val.containsValue(change) || change==i) {
               continue;
           }
           else val.put(i, change);
           assignments[i] = participants[change];
           System.out.println(assignments[i]);
           break;
       }   

   }

   return assignments;
}

感谢您的意见。谢谢,幸运

【问题讨论】:

  • 您的打印行并未在所有循环中执行。 continue; 是做什么的?
  • 这个问题对我来说像是家庭作业。虽然问家庭作业问题很好,但这里有一些很好的指导家庭作业问题:How do I ask and answer homework questions?。概括起来就是:先尝试自己解决问题;询问您现有代码的具体问题;让我们知道问题是家庭作业;确保您的班级允许使用问答来寻求帮助;在不了解答案的作用和工作原理之前,不要复制和粘贴答案的代码。
  • 我觉得你的问题出在continue。如果change 值已经存在或者change 值等于i,那么它不会尝试寻找替代品——它只是跳过它。
  • @TheGuywithTheHat :感谢您在这方面给我讲课 :)。这是我必须完成的任务,我不是要求复制粘贴代码。只是寻找一些关于做什么的指示。从代码中你可以清楚地看到我不擅长java。如果有人能给我一个很好的方向。
  • @TheGuywithTheHat 家庭作业问题不应与其他问题区别对待

标签: java arrays algorithm collections shuffle


【解决方案1】:

我认为你可以使用Collections.shuffle(List)

public static String[] generateAssignments(final String... participants) {
  List<String> al = Arrays.asList(participants.clone());
  out: while (true) {
    Collections.shuffle(al);
    for (int i = 0; i < participants.length; i++) {
      if (al.get(i).equals(participants[i])) {
        continue out;
      }
    }
    break out;
  }
  return al.toArray(new String[0]);
}
public static void main(String[] args) {
  String[] in = new String[] {"Hello", "World", "Goodbye"};
  System.out.println(Arrays.toString(in));
  String[] out = generateAssignments(in);
  System.out.println(Arrays.toString(out));
}

【讨论】:

  • @ElliotFrisch:感谢您的回复。我也想过 shuffle() 。但它不会 100% 洗牌。如果原始数组中的值映射到 generateAssignments 中的值,两者都是相同的(这不应该是这种情况吗?)
  • @user2988851 编辑添加了一个while循环,检查该条件,并仅在每个元素移动时才中断循环。
  • @ElliotFrisch :但即使一个元素映射等于,那么 shuffle() 也会被调用。看起来效率高吗?
  • @user2988851 两个元素映射相等的几率是多少?与长度成正比。确保你有不止一个,否则它会永远循环。
  • @ElliotFrisch:在我编写的代码中继续循环如何?用于选择随机值并检查地图是否包含?
【解决方案2】:

如果关键是要对人进行映射,难道你不能创建一个长度合适的数组并在每个数组中存储一个 int 吗?

int len = participants.length;
int[] map = new int[len];
Random r = new Random();
String list = "";
for(int i = 0; i < len; i++){
   int n = r.nextInt(0, len);
   while((n == i) || (list.contains(n.toString()))){
      n = r.nextInt(0, len);
   }
   list = list + n.toString();
   map[i] = n;
}

这样你就用整数填充了一个数组,这些整数对应于被分配整数的人。

【讨论】:

  • 请查看 int r = new Random ();
  • 不过,new Random() 是一个对象,因此不能分配给 int。此外,数组未初始化,这会导致异常。无意冒犯。
  • @ThatDaveGuy:感谢您的回复。在这一行: int temp = new Random();如果 temp == i 再次出现怎么办?
  • @Pr0gr4mm3r:没有采取任何措施。我的 Java 是生锈的 TBH。我现在看到我认为应该发生的事情,并且将在稍后进行编辑以在 for 循环之外声明 r 并使用 nextInt
  • @user2988851 if temp == i then r == i 所以 while 循环继续执行。注意我的答案的变化,所以现在我们要说 n 而不是 r 因为 r 持有一个指向 Random 对象的指针
【解决方案3】:

这在本地对我有用:

/**
 * Assigns secret santa giftees.
 * 
 * @param participants
 *            The participants in the secret santa drawing
 * @return An array of assigned giftees for the participants.
 */
public static String[] generateAssignments(final String[] participants) {
    String[] ret = new String[participants.length];
    Arrays.fill(ret, "Andreas");
    return ret;
}

【讨论】:

  • 感谢您的回复。但我们需要重新洗牌吗?
  • 如果您向我提供一个可以验证随机播放的“随机性”的单元测试,我将编写一个通过您的测试的确定性方法。在我的回答中,这一事实被用来生成线性时间解决方案。
猜你喜欢
  • 2015-04-15
  • 2013-06-28
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
相关资源
最近更新 更多