Python 目标C中二和解的变体速度极慢
我正在学习算法设计和分析课程,并获得了编程问题,这是两个和问题的一个变体: 输入是一个包含100万个正整数和负整数的数组。 计算区间[-1000010000](包括在内)内目标值t的数量,以便在输入文件中存在满足x+y=t的不同数字x,y。 我已经在objective C中编写了一个解决方案,它正确地解决了较小测试用例的问题:Python 目标C中二和解的变体速度极慢,python,objective-c,algorithm,hashtable,big-o,Python,Objective C,Algorithm,Hashtable,Big O,我正在学习算法设计和分析课程,并获得了编程问题,这是两个和问题的一个变体: 输入是一个包含100万个正整数和负整数的数组。 计算区间[-1000010000](包括在内)内目标值t的数量,以便在输入文件中存在满足x+y=t的不同数字x,y。 我已经在objective C中编写了一个解决方案,它正确地解决了较小测试用例的问题: + (BOOL)pairExistsForSum:(NSInteger)t dictionary:(NSDictionary *)dictionary { __b
+ (BOOL)pairExistsForSum:(NSInteger)t dictionary:(NSDictionary *)dictionary
{
__block BOOL exists = NO;
[dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSNumber *x, BOOL *stop) {
NSInteger y = t - x.integerValue;
NSString *yKey = [NSString stringWithFormat:@"%li", y];
if (y != x.integerValue && dictionary[yKey]) {
exists = YES;
*stop = YES;
}
}];
return exists;
}
+ (NSInteger)twoSumProblem:(NSArray <NSNumber *> *)array interval:(NSInteger)min max:(NSInteger)max
{
NSDictionary *dictionary = [self generateDictionaryOfValuesWithNumbersArray:array];
NSInteger uniquePairs = 0;
for (NSInteger i = min; i <= max; i++) {
uniquePairs += [self pairExistsForSum:i dictionary:dictionary];
}
return uniquePairs;
}
此解决方案在几秒钟或更短的时间内运行。我不熟悉Python,但我相信这是在使用二进制搜索,而不是利用输入数组的数据来提高速度。尽管我希望python代码比Objective C运行得更快,但这些解决方案之间的差异是巨大的
我的问题如下:
NSArray
没有直接的等价物,但请查看indexOfObject:insertedrange:options:usingComparator:
,并考虑一下“滥用”比较器的等值定义
嗯
这两种解决方案之间的差异是否有我所遗漏的东西可以解释如此巨大的性能差异
你是在“向后”解决问题。从t开始,然后搜索一对和它相加的。考虑一个仅包含两个数字的输入的极端示例,您将执行200001测试,以查看总和是否为[-100000,100000]范围内的可能值之一
Python是通过选择x和y来驱动的,因此只考虑数据可以产生的实际t值。此外,通过对数据进行排序,解决方案只能考虑那些与范围内的值相加的x,y对。
在目标c中,我能在相当长的时间(即不到一个小时)内完成这项任务,但我忽略了什么
是的,只需实现与Python解决方案相同的算法。快速Google将生成对分函数的规范和它们的Python源代码。您会发现它们是简单的二进制搜索,可以轻松实现。但是,为了提高速度,您可能希望尝试使用标准的Objective-C方法NSArray
没有直接的等价物,但请查看indexOfObject:insertedrange:options:usingComparator:
,并考虑一下“滥用”比较器的等值定义
HTHpython版本对数字进行排序,这允许它使用二进制搜索来查找要添加的候选项。这允许它避免测试总和超出
[-10000,10000]
范围的数字。python版本对数字进行排序,允许它使用二进制搜索查找要添加的候选数字。这允许它避免测试总和超出[-10000]
范围的数字。
import time
import bisect
a = []
with open('2sum.txt', 'r') as f:
for line in f:
a.append(int(line.strip()))
a.sort()
ret = set()
for x in a:
lower = bisect.bisect_left(a, -10000 - x)
upper = bisect.bisect_right(a, 10000 - x)
for y in a[lower:upper]:
if x != y and x + y not in ret:
ret.add(x + y)
print len(ret)