测验中我有一个问题:
If input data of randomList are 4 5 1 2 3 4
Results are:
pick(4) -> 4 4
pick(1) -> 1
pick(2) -> 2
pick(6) -> there is no value
这些是默认代码,我们可以随意将任何代码放在任何地方:
public static void main(String[] args){
List<Integer> randomList = new ArrayList<>();
for(int i = 0; i < 100000000; i++) {
randomList.add(new Random().nextInt());
}
.....
System.out.println("result = " + pick(new Random().nextInt()));
问题是,最有效的方法pick()优于O(n)的方法是什么?
这是我的O(n)版本:
static List<Integer> list2 = new ArrayList<>();
public static void main(String[] args){
List<Integer> randomList = new ArrayList<>();
for(int i = 0; i < 10; i++) {
randomList.add(new Random().nextInt(5)+1);
}
list2 = randomList;
System.out.println("result = " + pick(new Random().nextInt(5)+1));
}
public static String pick(int rand) {
String result = "";
System.out.println("search = " + rand);
for(Integer s : list2) {
if(s == rand) {
result = result + " " + rand;
}
}
return result;
}
非常感谢您。
答案 0 :(得分:4)
鉴于您的约束,除O(n)外没有更好的搜索算法。原因:
这种更好的唯一方法是将数据集移动到其他数据结构(例如Map)。然后,您将因加载数据而遭受O(n)罚款,但此后您将能够在恒定时间内找到这些值。
答案 1 :(得分:3)
如果您使用的Map
的键是您的输入值,而值是频率,那么Map
将在O(1)
的时间内找到一个键。字符串的构造将与键的频率成正比。因此,代码可能如下:
Map<Integer, Integer> mapList = new HashMap<>();
public static void main(String[] args){
for(int i = 0; i < 10; i++) {
int key = new Random().nextInt(5)+1;
if (mapList.contains(key)) {
mapList.put(key, mapList.get(key) + 1);
} else {
mapList.put(key, 1);
}
}
System.out.println("result = " + pick(new Random().nextInt(5)+1));
}
public static String pick(int rand) {
Integer count = mapList.get(rand);
if (count == null) {
return "";
}
StringJoiner sj = new StringJoiner(" ");
for (int i = 0; i < count; i++) {
sj.add(rand);
}
return sj.toString();
}
修改
如@Pshemo所建议,StringJoiner
代替StringBuilder,因为它更紧凑并且不会为最后一个字符添加多余的空间。