问题陈述
编写一个程序,生成数字1到的随机排列 10.要生成随机排列,您需要使用数字1到10填充数组,以便阵列中没有两个条目具有相同的 内容。你可以通过调用Random.nextInt来强行完成 直到它产生一个尚未在数组中的值。相反,你 应该实施一种智能方法。制作第二个数组并填充它 数字1到10.然后随机选择其中一个,删除它,然后 将它附加到排列数组。重复10次。实现一个类 PermutationGenerator,方法为int [] nextPermutation
我在理解问题所说的内容方面遇到了一些麻烦。
我的解释是,我们需要将数字1-10放在数组中,给出一些随机数,范围从1到10。
我解决这个问题的方法是简单地添加一个数组并进行循环,然后检查下一个随机数是否已经在数组中。但是根据这个问题,这被视为"蛮力"
通过实施第二个阵列,我不确定我的书是什么意思。如果我赢得第二个阵列,我仍然需要检查阵列中是否有东西?
我的尝试 首先,我只是试图将10个随机数放入一个数组中,而忽略了它们必须区分的部分。继承人我有什么
private int[] arr;
private Random randNum;
public seq()
{
randNum = new Random();
arr = new int[10];
}
public int getRandNum()
{
int newNum = randNum.nextInt(10)+1;
return newNum;
}
public int [] filledArr()
{
for (int i = 0 ; i<arr.length; i++)
{
arr[i] = getRandNum();
}
return arr;
}
问题在于,我必须拨打getRandNum()
10次才能获得10个不同的号码,然后拨打filledArr
将其放入。这很难打字。有没有更好的办法?我想我也可以在主内部制作一个for循环,然后这样做?这看起来非常低效。
感谢任何建议
另一个 尝试
class seq
{
private int[] arr;
private int[] filledArr;
private Random randNum;
public seq()
{
randNum = new Random();
arr = new int[10];
filledArr = new int[10];
}
public int [] generateNewArr()
{
for(int i = 1; i< 11 ; i++)
{
filledArr[i] = i;
}
return filledArr;
}
public int [] newArr()
{
for(int i=1; i < 11 ; i++)
{
int newRandNum = //RANDOM NUMBER IN filledArr;
arr[i] = newRandNum;
// REMOVE that random number from filledArr
}
}
}
与ARRAYLISTS的关系
import java.util.Random;
import java.util.ArrayList;
class seq
{
private ArrayList<Integer> arrListOne;
private ArrayList<Integer> arrListTwo;
private Random num;
public seq()
{
num = new Random();
arrListOne = new ArrayList<Integer>(10);
arrListTwo = new ArrayList<Integer>(10);
}
public ArrayList getFilledArr()
{
for(int i = 1; i < arrListOne.size()+1 ; i++)
{
arrListOne.add(i);
}
return arrListOne;
}
public ArrayList randNewArr()
{
for(int i = 0 ; i < 10 ; i++)
{
int randNum = num.nextInt(arrListOne.size())+1;
arrListTwo.add(arrListOne.get(randNum));
arrListOne.remove(arrListOne.get(randNum));
}
return arrListTwo;
}
public String toString()
{
String output = "The Randomized ArrayList is";
output+=arrListTwo;
return output;
}
}
public class Sequence
{
public static void main(String [] args)
{
seq seqObj = new seq();
seqObj.getFilledArr();
seqObj.randNewArr();
System.out.println(seqObj.toString());
}
}
答案 0 :(得分:1)
这个问题是我必须调用getRandNum()10次以获得10个不同的数字,然后调用filledArr将其放入其中。这很难打字。还有更好的方法吗?
是的。
使用此:
public int [] filledArr()
{
for (int i = 0 ; i < arr.length; i++)
{
arr[i] = randNum.nextInt(10)+1;
}
return arr;
}
因此您的编码较少且结果相同。
答案 1 :(得分:1)
问题只是这样说:
制作一个数字为1-10的数组(不必随意排序)。然后 生成1-10之间的随机数并选择该数字并删除该索引 来自你之前创建的数组。
粗略的实施将是:
ArrayList nums = new ArrayList<Integer>(); // The arraylist with numbers from 1-10
for(int i = 1; i < 11; i++;)
nums.add(i);
Random r = new Random();
int x = r.nextInt(10);
int[] finalNums = new int[2];
finalNums[0] = nums.get(x);
nums.remove(x); // Remove the number at this index so it won;t be picked up again
x = r.nextInt(9); // Since we removed one index from arraylist, so total elements are now nine instead of 10.
finalNums[1] = nums.get(x);
nums.remove(x);
那么区别是什么?在这种方法中,您确信它不会两次选择相同的数字。为什么?因为您在选择号码后立即删除该号码,因此不会再次接收号码。
修改强>
至于你在ArrayList中尝试询问你在main
块中写了什么的尝试,你只需要按顺序调用你在课堂上创建的两个方法。它可以在主要块中:
public class Sequence
{
// You need one main method atleast to run the code
public static void main(String[] args){
seq seqObj = new seq();
System.out.println(seq.getRandomArray());
}
}
或者您也可以在seq
课程中调用这些方法&#39;构造:
public seq()
{
randNum = new Random();
arr = new int[10];
filledArr = new int[10];
this.getFilledArr();
this.randNewArr();
}
另外需要注意的是,显示ArrayList输出的方法不没问题。对您的代码稍作修正:
import java.util.Random;
import java.util.ArrayList;
class seq
{
private ArrayList<Integer> arrListOne;
private ArrayList<Integer> arrListTwo;
private Random num;
public seq()
{
num = new Random();
arrListOne = new ArrayList<Integer>();
arrListTwo = new ArrayList<Integer>();
getFillerArr();
randNewArr();
}
// You dont have to return ArrayList here
public void getFilledArr()
{
for(int i = 1; i < 11 ; i++)
{
arrListOne.add(i);
}
}
// You dont have to return ArrayList here
public void randNewArr()
{
for(int i = 0 ; i < 10 ; i++)
{
int randNum = num.nextInt(arrListOne.size())+1;
arrListTwo.add(arrListOne.get(randNum));
arrListOne.remove(arrListOne.get(randNum));
}
}
// A method that returns you random array list so you can easily use it following rules of encapsulation
public ArrayList<Integer> getRandomArray() {
return this.arrListTwo;
}
}
public class Sequence
{
public static void main(String[] args){
seq seqObj = new seq();
System.out.println(seq.getRandomArray());
}
}
编辑#2:
对于negative bound exception
的问题,这就是您的代码应该如何:
public seq()
{
num = new Random();
// Do not try to specify size of Array List here. THey don't have fixed size.
arrListOne = new ArrayList<Integer>();
arrListTwo = new ArrayList<Integer>();
getFillerArr();
randNewArr();
}
public void getFilledArr()
{
// Manually iterate for 10 elements.
for(int i = 1; i < 11 ; i++)
{
arrListOne.add(i);
}
}
public ArrayList randNewArr()
{
for(int i = 0 ; i < 10 ; i++)
{
// Do not add +1 here, actual array size is already 1 less than the size you get from #size() method.
int randNum = num.nextInt(arrListOne.size());
arrListTwo.add(arrListOne.get(randNum));
arrListOne.remove(arrListOne.get(randNum));
}
return arrListTwo;
}
说明:
arrListOne = new ArrayList<Integer>(10);
在这里,您尝试创建固定大小为10的数组列表?但ArrayLists没有固定的大小。所以这不会起作用。因此你的这个循环也失败了:
public ArrayList getFilledArr()
{
for(int i = 1; i < arrListOne.size()+1 ; i++)
{
arrListOne.add(i);
}
return arrListOne;
}
(数组列表的大小为0,因此循环不会运行)。
因此,在获取随机数时会得到该异常。
PS:我很糟糕,自从我做java之后已经有一段时间了。不知何故,我在阅读该代码时忽略了它。答案 2 :(得分:1)
提示:似乎你并没有理解所建议的“智能”方法;它应该按如下方式进行:
生成一个包含10个整数的数组,不是随机,只需将所有数字从1到10排序。 还生成一个空数组。
在循环中,从第一个数组中选取一个随机元素并将其移动到第二个数组。
你可以从这里继续吗?
编辑:第三次尝试的主要问题是:
在int randNum = num.nextInt(arrListOne.size())+1;
中,你似乎混淆了两件事,整数的值,以及它在数组中的位置。您想要在一个范围内随机选择的内容(从零开始)是位置,因此您应该编写
int randPos = num.nextInt(arrListOne.size());
此外,类的结构不是很好,你应该使用nextPermutation()
方法编写一个类,所有的数组/列表都应该存在于该方法中,唯一的state
为作为类中的字段保存应该是随机生成器。我建议在这个结构中编码所有代码:
public class PermGen {
public final int SIZE = 10;
private final Random rand = new Random();
/* returns a new permutation of elements from 1 to 10 (size) */
public int[] nextPermutation() {
// create the two lists/arrays here
int[] res = new int[SIZE];
List<Integer> list1 = new ArrayList<>(); // or LinkedList
// ... fill list1
for( int i = 0; i < SIZE; i++ ) {
// pick a random pos1 from list, move the element to res
// ...
res[i] = list1.remove(randpos); // move the element
}
return res;
}
}
答案 3 :(得分:1)
只是一个想法:
import java.util.ArrayList;
int LEN = 10;
ArrayList<Integer> oldArray = new ArrayList<Integer>();
for (int i = 0; i < LEN; i++)
oldArray.add(i+1);
int[] newArray = new int[LEN];
for (int i = 0; i < LEN; i++) {
int pos = (int)(Math.random() * oldArray.size());
newArray[i] = oldArray.remove(pos);
}
不确定它是否符合标准(使用ArrayList和所有,但只是建议)
答案 4 :(得分:1)
因为这是一个家庭作业问题,显然,我不想给你实际代码,而是要描述它。 (因为你说过不是,我在上面添加了一个完整的答案,但决定也保留这个解释。)
基本上,你是“洗牌一副牌”。首先将数组初始化为顺序1..10。
现在,您可以通过从1..10开始在牌组中循环来“洗牌”牌组,随机选择大于或等于(“在......前面或前面”)你的光标位置。 交换两张卡片。
这在功能上等同于“从另一个阵列中随机删除一张卡片”,但它利用了这样一个事实:“一堆混洗卡片”的增长率与“随机抽取的一堆排序卡片”完全相同收缩。因此,它只能在一个数组中完成。混洗部分位于光标后面; (最初)有序部分是在前或后。
在一个传递中,你有一张非常洗牌的牌,据说不含重复牌。
答案 5 :(得分:1)
伪代码(不是Java):
$ mix test
.
Finished in 0.2 seconds
1 test, 0 failures
当这个版本的算法运行时,超出光标Card deck[], temp;
int i, j;
// fill the deck
for (i = 0; i < 10; i++) deck[i] = i;
// Shuffle 'em. Runs stern-to-stem because of 'rand()'
for (i = 9; i > 0; i--) { // no need for (i == 0) ...
j = rand(i); // returns value in the inclusive range [0..i]
// it's just fine if (i == j) ... although it usually won't be ...
temp = deck[i]; // set-aside the card in the cursor-position
deck[i] = deck[j]; // replace it with the randomly-chosen card
deck[j] = temp; // then put the original card where it can get picked
}
位置的卡片就是洗牌,而i
中的卡片是半排序的从中随机抽取的牌。 (这个池开始完全排序,但随着元素被交换进去,它变得没有排序,但是谁在乎。)
您将看到此算法在一个传递中的单个数组中工作,产生一个彻底改组的套牌,不包含重复项。该算法与使用两个数组的算法相同,但效率更高:数组就地改组,从不调整大小。
可以使用任何容器类(可调整大小或不可调整大小),但所选容器应该是一个底层实现,允许以相当的速度检索任何随机选择的元素,无论它在何处。例如,“链表”不是一个有效的选择。