我在O(n)
时间复杂度中遇到了一个需要解决的问题:
“给定一个数字列表和数字x。查找列表中是否有任何2个数字加起来为x?”
这是我的解决方案:
public class SumMatchResult {
public static void main(String[] args){
int[] numberList = {6,1,8,7,4,6};
int requiredSum = 8;
boolean isSumPresent = checkSumPresentHash(numberList,requiredSum);
if(isSumPresent) {
System.out.println("Numbers exist");
}else {
System.out.println("Numbers donot exist");
}
}
private static boolean checkSumPresentHash(int[] numberList, int requiredSum) {
Map<Integer, Integer> m = new HashMap<Integer,Integer>();
int count = 0;
for(int i=0;i<numberList.length;i++){
m.put(i, numberList[i]);
}
for(int i=0;i<numberList.length;i++){
if(m.containsValue(requiredSum - numberList[i])){
count++;
}
}
if(count>1){
return true;
}
return false;
}
}
我正在使用HashMap.containsValue()
而不是使用HashSet.contains()
,而O(1)
肯定会有{3,6,4,4,7}
的复杂性,因为我必须考虑我的输入可能包含相同值的情况。例如,在上述情况下,我可以为sum 8
匹配一组输入值true
,该值应返回HashMap.containsValue()
。
我上面的解决方案的时间复杂度取决于containsValue()
方法的复杂性。请详细说明{{1}}方法的时间复杂度,并建议我在时间复杂度方面是否有更好的解决方案来解决上述问题。谢谢。
答案 0 :(得分:16)
要回答标题中的问题 - 正如其他人所提到的,containsValue
是O(n),因为没有密钥它不知道它在哪里,算法必须遍历存储的所有值在地图上。
要回答问题正文中的问题 - 如何解决问题 - 只需考虑一下是否真的需要一个可以计算每个数字的实例数量的通用地图。我的意思是,如果一个数字的外观不止一个是x / 2,你只关心 时间,对吗?那对我来说就像一个角落的味道。只需添加一个检查该角落案例的测试 - 例如在您的集合构建循环中嵌入if (numberList[i] == requiredSum/2) half++
,然后再添加if (requiredSum % 2 == 0 && half == 2) return true
(请参阅下面的其他变体)。
然后你可以迭代整个集合并为每个项目检查requiredSum-item
是否也出现在集合中。
总结(尽可能早退):
Set<Integer> seen = new HashSet<Integer>();
boolean halfSeen = false;
for (int num : numberList) {
if (num == requiredSum/2 && requiredSum % 2 == 0) {
if (halfSeen) return true;
halfSeen = true;
} else {
seen.add(num);
}
}
for (int num : seen) {
if (seen.contains(requiredSum - num)) return true;
}
return false;
答案 1 :(得分:12)
HashMap本质上是一个键值存储,它可以访问复杂度为O(1)的密钥。但是,检查一个值,HashMap无法做任何事情,但检查所有值并查看它们是否与您正在搜索的值相等。因此,复杂度为O(n),其中n是HashMap中元素的数量。
另一方面:您正在查找其盒装类型(整数)集合中的原始值(int)。这意味着每次在HashMap上调用方法时,Java都需要为您设置原始值:http://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html
答案 2 :(得分:3)
HashMap.containsValue复杂度为O(n)。但是n并不完全是地图大小,而是散列表大小,因为即使map size = 0,containsValue也会遍历所有表元素。 假设我们创建了一个初始容量= 1024的空映射.containsValue必须通过1024个元素哈希表数组:
public boolean containsValue(Object value) {
if (value == null)
return containsNullValue();
Entry[] tab = table;
for (int i = 0; i < tab.length ; i++)
for (Entry e = tab[i] ; e != null ; e = e.next)
if (value.equals(e.value))
return true;
return false;
}
答案 3 :(得分:0)
HashMap
中没有标记任何值的索引,因此,要使用 containsValue()
查找值,您必须遍历 HashMap
的所有值。< /p>
请注意,这里的复杂性 O(n)
是 HashMap 中值的数量,不是我们通常用来表示其复杂性的键/大小。