一个例子: 我有一套
[a, b, c, d, e, f, g, h]
我想选择其中三个但不重复, 所以
[e, g, a]
是正确的子集
[h, c, h]
不正确。
知道如何轻松清晰地制作它吗?
为了清楚起见: 我有一组测验的问题。它不是生成一个字母子集。 我想要的是: String数组的子集或数组的索引子集,例如从0到10。 因为它是一个测验,所以元素不能重复。
答案 0 :(得分:1)
如果O(n)适合您,您可以遍历这些项目。对于每个项目,您可以随机选择它。
Set<Character> newSet = ...;
for (Char elem : set) {
if (randomFunction()) {
newSet.add(elem);
}
}
答案 1 :(得分:1)
如果不考虑额外的内存使用情况,您可以在Collections.shuffle()
上尝试使用List
并获取前三个值。
Set<Character> set = new TreeSet<Character>();
for (char c = 'a'; c < 'i'; c++) {
set.add(c);
}
List<Character> list = new ArrayList<Character>(set);
Collections.shuffle(list);
System.out.println(list.subList(0, 3));
你也可以试试这个
Random random = new Random();
int index = 0;
List<Character> list = new ArrayList<Character>(set);
Set<Character> newSet = new HashSet<Character>();
while (newSet.size() < 3) {
index = random.nextInt(set.size());
newSet.add(list.get(index));
}
答案 2 :(得分:0)
如果这是针对学校的,您可能需要避免使用方便的方法。这是一个简单的方法:
ArrayList<String> al = new ArrayList<String>();
al.add("a");
al.add("b");
al.add("c");
al.add("d");
al.add("e");
al.add("f");
al.add("g");
al.add("h");
int chooseNum = 3;
Random rand = new Random();
int index;
String val;
while (chooseNum > 0 && chooseNum <= al.size()) {
index = rand.nextInt(al.size());
val = al.remove(index);
System.out.print(val);
System.out.print(" ");
chooseNum--;
}
答案 3 :(得分:0)
我认为Braj的答案是最优雅的,但如果性能对您很重要,可以选择以下几种方式:
这就像Braj的回答。除了它是O(k)而不是O(n)(其中k是拾取的元素的数量,n是输入的大小)。
/**
* Randomly picks elements from a set.
*
* @param k Number of elements to choose.
* @return A list containg k elements from the set.
*/
public Set<T> randomPick(int k) {
T[] a = (T[]) new Object[k];
a = this.inputSet.toArray(a);
int n = a.length;
if (k < 0 || k > n) {
String msg = String.format(
"Cannot pick %0 elements from a set that contains %1 elements.",
k, n);
throw new IllegalArgumentException(msg);
}
Random random = new Random();
for (int i = 0; i < k; i++) {
// Swap a[i] with a random element in the unswapped elements
int r = i + random.nextInt(n - i);
T temp = a[i];
a[i] = a[r];
a[r] = temp;
}
T[] output = Arrays.copyOfRange(a, 0, k);
return new HashSet<T>(Arrays.asList(output));
}
这非常简单。
我认为如果k很小则会更快,而当k接近n时效率会降低。
/**
* Randomly picks elements from a set.
*
* @param k Number of elements to choose.
* @return A list containg k elements from the set.
*/
public Set<T> randomPick2(int k) {
List<T> list = new ArrayList<T>(this.inputSet);
int n = list.size();
if (k < 0 || k > n) {
String msg = String.format(
"Cannot pick %0 elements from a set that contains %1 elements.",
k, n);
throw new IllegalArgumentException(msg);
}
T[] a = (T[]) new Object[k];
a = this.inputSet.toArray(a);
Random random = new Random();
Set<T> output = new HashSet<T>(k);
while (output.size() < k) {
int r = random.nextInt(n);
output.add(a[r]);
}
return output;
}