题目:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
考察点:
- 这是一道LeetCode上非常基础的一道算法题。主要考察的就是哈希表查找对应键值的时间复杂度O(1)。
解法:
一、暴力循环
- 循环数组中每一个数字和之后的数字做比较,若两者和为目标数值return两个数字的index
- 时间复杂度O(n²)
- (NSArray *)twoSums:(NSArray <NSNumber *>*)numArray equalTo: (int) total {
for (int i = 0; i < numArray.count; i++) {
for (int j = i + 1; j < numArray.count; j++) {
int q = [numArray[i] intValue];
int w = [numArray[j] intValue];
if(q + w == total) {
return @[@(i), @(j)];
}
}
}
return nil;
}
二、使用哈希表
- 在循环数组将值插入表中的同时,查找哈希表中是否含有目标值减去当前值的key。如果存在将其立即返回
- 时间复杂度:O(n),因为我们只遍历了包含有 n 个元素的列表一次。在表中进行的每次查找只花费 O(1) 的时间。这样就降低了算法的时间复杂度
- NSDictionary底层就是哈希表所以这里我们用NSDictionary代替
- (NSArray *)dictTwoSums:(NSArray <NSNumber *>*)numArray equalTo: (int) total {
NSMutableDictionary *usedNums = [NSMutableDictionary dictionaryWithCapacity:numArray.count];
for (int i = 0; i < numArray.count; i++) {
int q = [numArray[i] intValue];
NSNumber *w = [NSNumber numberWithInt:(total - q)];
if([[usedNums allKeys]containsObject:w]) {
return @[@(i), [usedNums objectForKey:w]];
} else {
[usedNums setObject:@(i) forKey:numArray[i]];
}
}
return nil;
}
总结
- 这道题让我了解并熟悉了哈希表,理解了这个算法对你之后编程的思路的思考有很大帮助
- 如果想要了解更多hash表、NSDictionary的相关知识可以看这篇文章,我觉得写的还是很不错的
https://www.jianshu.com/p/0d7cd6341f65
思考
- 这两个算法写完思路虽然比原来扩展了,但这两个方法执行起来的时间,不管数组长短,元素位置变化,总是第一个方法实现的时间更短。背后的原因是因为NSDictionary的相关方法增加了开销,还是其他原因,值得思考。