一个"2-SUM"问题
题目要求:
Download the text file here. (Right click and save link as).
The goal of this problem is to implement a variant of the 2-SUM algorithm (covered in the Week 6 lecture on hash table applications).
The file contains 1 million integers, both positive and negative (there might be some repetitions!).This is your array of integers, with the ith row of the file specifying the ith entry of the array.
Your task is to compute the number of target values t in the interval [-10000,10000] (inclusive) such that there are distinct numbers x,y in the input file that satisfy x+y=t. (NOTE: ensuring distinctness requires a one-line addition to the algorithm from lecture.)
Write your numeric answer (an integer between 0 and 20001) in the space provided.
OPTIONAL CHALLENGE: If this problem is too easy for you, try implementing your own hash table for it. For example, you could compare performance under the chaining and open addressing approaches to resolving collisions.
大致意思是说,有一百万个数字(正负都有,且可能重复)。目标是要寻找到两个数x和y,使得x+y属于[-10000, 10000]的范围中,且x和y在所有数当中都是唯一存在的,最后输出所有可能的和的个数。
文件中的数据差不多是这样子的:
...
-92205919974
-65150999169
-96247986144
70191728682
-59670982771
-10202710755
-72167080349
-19221613985
80341418823
-79433686277
87351713416
6084932343
40801752610
44028247959
84203784346
-28120386474
59064431376
39436465566
-89458683408
-64200776240
-42582579303
-62656888535
55650079602
62954175548
33713639217
70259349593
-97472959477
41890148139
44216212976
26864335558
...
解题思路:
起初采用了最暴力的方法,直接把这些数字塞进一个hash table中,然后遍历着去查询(这个方法很不好,所以就不详述了),结果运行了很久都没有跑出结果,遂直接放弃这种方法。
这里的问题在于如下两点:
- 数据量多达一百万条;
- 大部分数对相加的和,远超要求的范围之外。
因此针对问题的实际情况进行了些许优化,大致思路如下:
- 假设X为文件中的一个数字;
- 创建一个hash table,它的键为X/10000,值为由对应X组成的set。这样就相当于把输入的数据以10000作为一个范围对其进行划分,最后划分成若干组数据,之所以要将10000作为划分的范围,是因为题目中要求数对的和在[-10000, 10000]的范围中,这样对于我们这里的hash table,给定一个key1,我们就能知道可能有哪些key2对应集合中的数与key1集合中的数相加,是可以在要求的范围中的;
- 具体而言,对于一个key1,可取的key2有:{-key1-2, -key1-1, -key1}这三个。注意因为之前的X/10000是整除,其结果为向下取整,如 -14000 / 10000 = -2;
- 在已知了key1与key2之后,对其集合中的数进行循环遍历,如果相加的和在题目要求的范围内,那么就将计数器加一。
利用上述思路,可以避免大量的不必要的运算,另外我们还可以对其进行进一步的优化:
- 对key1进行遍历的时候,只取key1小于或等于零的值,这样可以进一步减少重复计算;
- 创建一个保存结果的set,如果找到了满足要求的数对(x, y),那么就置result[x+y] = True,最后输出result的大小。
代码实现:
有了上述的思路,利用Python对其进行了实现,代码如下:
result = {}
dic = {}
input_file = open("algo1-programming_prob-2sum.txt")
# 读入数据
for line in input_file:
num = long(line)
key = num/10000
if key not in dic:
dic[key] = {}
# 这里记录数据出现的次数,用来判断该数是否是唯一的
if num in dic[key]:
dic[key][num] += 1
else:
dic[key][num] = 1
for key1 in dic:
# 忽略key1 > 0的情况,减少不必要的重复计算
if key1 > 0:
continue
# 根据给定的key1,可以推测出key2可取的值
for key2 in range(-key1-2, -key1 + 1):
if key2 in dic:
# 对key1和key2对应集合中的数进行遍历
for value2 in dic[key2]:
for value1 in dic[key1]:
# 判断这两个数是否是唯一的
if dic[key1][value1] != 1 or dic[key2][value2] != 1:
continue
sum_tmp = value1+value2
# 判断两数之和是否在题目要求的范围内
if abs(sum_tmp) <= 10000 and sum_tmp not in result:
result[sum] = True
# 输出结果
print len(result)
input_file.close()
这段代码在我的电脑上运行仅需要大约3-4秒的时间就能跑出结果(包含读取数据的I/O操作的时间),可见该方法有效地避免了大量不必要的计算。
另外,题目中要求找到唯一存在的数对(x, y),但是如果把代码中判断唯一性的那个条件判断去除,得到的结果也是一样的,这也许和给出的数据有关。
一个"2-SUM"问题的更多相关文章
- [LeetCode] Maximum Size Subarray Sum Equals k 最大子数组之和为k
Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If t ...
- [LeetCode] Two Sum III - Data structure design 两数之和之三 - 数据结构设计
Design and implement a TwoSum class. It should support the following operations:add and find. add - ...
- 数字和为sum的方法数
[编程题] 数字和为sum的方法数 给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数. 当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案. 输入描 ...
- ✡ leetcode 170. Two Sum III - Data structure design 设计two sum模式 --------- java
Design and implement a TwoSum class. It should support the following operations: add and find. add - ...
- 求和函数 sum详解
sum()的参数是一个list: >>> sum([1,2,3]) 6 >>> sum(range(1,3)) 3 还有一个比较有意思的用法 a = range(1 ...
- Sum 类型题目总结
Sum类的题目一般这样: input: nums[], target output: satisfied arrays/ lists/ number 拿到题目,首先分析: 1. 是几个数的sum 2. ...
- hdu 3415 Max Sum of Max-K-sub-sequence(单调队列)
题目链接:hdu 3415 Max Sum of Max-K-sub-sequence 题意: 给你一串形成环的数,让你找一段长度不大于k的子段使得和最大. 题解: 我们先把头和尾拼起来,令前i个数的 ...
- LeetCode OJ 209. Minimum Size Subarray Sum
Given an array of n positive integers and a positive integer s, find the minimal length of a subarra ...
- LeetCode算法题-Sum of Left Leaves(Java实现)
这是悦乐书的第217次更新,第230篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第85题(顺位题号是404).找到给定二叉树中所有左叶的总和.例如: 二叉树中有两个左叶 ...
- item 6: 当auto推导出一个不想要的类型时,使用显式类型初始化的语法
本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 Item 5解释了比起显式指定类型,使用auto来 ...
随机推荐
- Android studio 断点技巧
写代码不可避免有Bug,通常情况下除了日志最直接的调试手段就是debug:那么你的调试技术停留在哪一阶段呢?仅仅是下个断点单步执行吗?或者你知道 Evaluate Expression , 知道条件断 ...
- NioSocket相关知识
一.Nio简介 nio 是non-blocking的简称,在jdk1.4 里提供的新api .Sun 官方标榜的特性如下: 为所有的原始类型提供(Buffer)缓存支持.字符集编码解码解决方案. Ch ...
- 谈一谈Java8的函数式编程(二) --Java8中的流
流与集合 众所周知,日常开发与操作中涉及到集合的操作相当频繁,而java中对于集合的操作又是相当麻烦.这里你可能就有疑问了,我感觉平常开发的时候操作集合时不麻烦呀?那下面我们从一个例子说起. 计 ...
- 小程序地图map
wxml: <button class="button" bindtap="getlocation" style="margin-top:30p ...
- 教你怎么把iconfont转换成png透明图片
1.进入iconfont图标库,登陆.http://www.iconfont.cn/ 2.选择想要的图标加入购物车. 3.直接选中下载图标为png格式.
- python小工具:用python操作HP的Quality Center (二)----- 用异步方式提高速度
上接第一篇 http://www.cnblogs.com/sdet/p/6874631.html 在python中,很简单地能把http请求通过异步的方式发送,以下代码在python 3.6.0上运行 ...
- Git基础-打标签
打标签 同大多数 VCS 一样,Git 也可以对某一时间点上的版本打上标签.人们在发布某个软件版本(比如 v1.0 等等)的时候,经常这么做.本节我们一起来学习如何列出所有可用的标签,如何新建标签,以 ...
- SQL注入攻击[详解]
SQL注入攻击是黑客对数据库进行攻击的常用手段之一.随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多.但是由于程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候, ...
- WPF界面XAML中的if……else……
xaml本身并不支持if--else--,要用Converter替代if--else--来实现我们想要的效果,知者请速离开,不要浪费时间 需求:按照Window的WindowState来决定Gri ...
- C语言到C++(1) - 基本变化
说到C++和C语言的区别,大部分人都会想到面向对象和面向过程.然而这种说法并不准确.面向对象和面向过程指的是两种不同的程序设计思想,而C++与C是两种编程语言,难道C++就不能用于面向过程去解决问题吗 ...