【LeetCode】Two Sum && 【九度】题目1352:和为S的两个数字

133 篇文章 0 订阅
121 篇文章 2 订阅
Two Sum 
Total Accepted: 11827 Total Submissions: 59949 My Submissions
Given an array of integers, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
        关于求数组中两数之和为特定的某个数字,编程之美中有说明。
        最简单也最容易想到的方法,固定一个数字,然后扫描数组中的剩余数字,看累计和是否为target。这样时间复杂度很高,容易超时。
改进办法
        方法1、对原数组排序,然后让最小的数字和最大的数字相加,判断和target大小关系。如果比target大,说明最大数太大了,需要减小最大数,high左移一位。同理,如果比target小,说明最小数小了,右移一位,然后再次判断,一直到结果等于target为止,因为结果只有一个,直接返回结果即可。
        这里还有一个问题,就是保存数组下标的问题,因为求解的是index,可以使用map,但是有可能有重复数据,一定要注意处理。
        方法2、和1一样,需要处理下标的问题,和1不一样的是,扫描一遍数组,判断target-num[i]是否在numMap中,如果在,还需要判断target是否等于2*num[i],这一步是为了处理下标。
        关于2,用了两种方式,一种是排序,一种不排序。发现排序比不排序速度要快些。
        我觉得之所以会这样,是因为无序数组,有可能和为target的数据都出现在数组中的后半部分,而排序后的数组,最多只需要扫描一半数组,就会出现结果。举个例子,一组数据[3,5,6,3,9,2,11]target = 13。如果不排序扫描的话,一直要扫描到2才会出结果。如果排序的话,第一个数就得到结果了。

Java 方法1 AC 

public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int len = numbers.length;
        Map<Integer,List<Integer>> numMap = new HashMap<Integer,List<Integer>>();
        List<Integer> indexList = new ArrayList<Integer>();
        for(int i = 0; i < len; i++){
            indexList = numMap.get(numbers[i]);
            if(indexList == null){
                indexList = new ArrayList<Integer>();
            }
            indexList.add(i);
            numMap.put(numbers[i],indexList);
        }
        Arrays.sort(numbers);
        int []array = new int[2];
        int low = 0;
        int high = len-1;
        while(low < high){
            if(numbers[low] + numbers[high] > target){
                high--;
            }else if(numbers[low] + numbers[high] < target){
                low++;
            }else{
                break;
            }
        }
        if(numbers[low] == numbers[high]){
            indexList = numMap.get(numbers[low]);
            array[0] = indexList.get(0) + 1;
            array[1] = indexList.get(1) + 1;
        }else{
            array[0] = numMap.get(numbers[low]).get(0) + 1;
            array[1] = numMap.get(numbers[high]).get(0) + 1;
        }
        Arrays.sort(array);
        return array;
    }
}
Java 方法2 排序 AC 

public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int len = numbers.length;
        Map<Integer,List<Integer>> numMap = new HashMap<Integer,List<Integer>>();
        List<Integer> indexList = new ArrayList<Integer>();
        for(int i = 0; i < len; i++){
            indexList = numMap.get(numbers[i]);
            if(indexList == null){
                indexList = new ArrayList<Integer>();
            }
            indexList.add(i);
            numMap.put(numbers[i],indexList);
        }
        Arrays.sort(numbers);
        int []array = new int[2];
        for(int i = 0; i < len; i++){
            int result = target - numbers[i];
            if(numMap.containsKey(result)){
                if (result == numbers[i]) {
            		List<Integer> keyList = numMap.get(numbers[i]);
            		array[0] = keyList.get(0)+1;
            		array[1] = keyList.get(1)+1;
				}else {
					array[0] = numMap.get(numbers[i]).get(0)+1;
	            	array[1] = numMap.get(result).get(0)+1 ;
				}
            	break;
            }
        }
        Arrays.sort(array);
        return array;
    }
}
Java 方法2 不排序 AC 

public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int len = numbers.length;
        Map<Integer,List<Integer>> numMap = new HashMap<Integer,List<Integer>>();
        List<Integer> indexList = new ArrayList<Integer>();
        for(int i = 0; i < len; i++){
            indexList = numMap.get(numbers[i]);
            if(indexList == null){
                indexList = new ArrayList<Integer>();
            }
            indexList.add(i);
            numMap.put(numbers[i],indexList);
        }
        int []array = new int[2];
        for(int i = 0; i < len; i++){
            int result = target - numbers[i];
            if(numMap.containsKey(result)){
                if (result == numbers[i]) {
            		List<Integer> keyList = numMap.get(numbers[i]);
            		if(keyList.size() == 1){
            		    continue;
            		}
            		array[0] = keyList.get(0)+1;
            		array[1] = keyList.get(1)+1;
				}else {
					array[0] = numMap.get(numbers[i]).get(0)+1;
	            	array[1] = numMap.get(result).get(0)+1 ;
				}
            	break;
            }
        }
        Arrays.sort(array);
        return array;
    }
}

Update【2014年6月30日13:33:35】 更新Java简单方法以及python代码,同时更新疑问。
1、Java代码最新最简单的解决方式,耗时384ms
Java AC

public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        Map<Integer, Integer> numMap = new HashMap<Integer, Integer>();
        int len = numbers.length;
        int array[] = new int[2];
        for(int i = 0; i < len; i++){
            if(numMap.containsKey(target - numbers[i])){
                array[0] = numMap.get(target - numbers[i]) + 1;
                array[1] = i + 1;
            }else{
                numMap.put(numbers[i], i);
            }
        }
        return array;
    }
}

2、python速度还可以,172ms
python AC

class Solution:
    # @return a tuple, (index1, index2)
    def twoSum(self, num, target):
        numMap = {}
        alen = len(num)
        array = [0, 0]
        for i in range(alen):
            if numMap.get(target - num[i]) != None:
                array[0] = numMap.get(target - num[i]) + 1
                array[1] = i + 1;
            else:
                numMap[num[i]] = i
        return array

3、疑问

      如果数组中有重复数据,其实输出是不太一样的,例如输入为[2,2,3,7,6],target为5,前三种javaAC代码输出为[1,3],更新的这两种输出为[2,3],不过都AC了,不知道LeetCode是怎么判断结果的。     

2、【九度】题目1352:和为S的两个数字       
这个题目和Two Sum是完全一样的,但是不需要处理下标问题,所以处理起来要容易的多。
题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输入
每个测试案例包括两行:
第一行包含一个整数n和k,n表示数组中的元素个数,k表示两数之和。其中1 <= n <= 10^6,k为int
第二行包含n个整数,每个数组均为int类型。
输出
对应每个测试案例,输出两个数,小的先输出。如果找不到,则输出“-1 -1”
样例输入
6 15
1 2 4 7 11 15
样例输出
4 11
答疑
解题遇到问题?分享解题心得?讨论本题请访问: http://t.jobdu.com/thread-8075-1-1.html

Java AC

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
 
public class Main {
    /*
     * 1352
     */
    public static void main(String[] args) throws Exception {
        StreamTokenizer st = new StreamTokenizer
        			(new BufferedReader(new InputStreamReader(System.in)));
        while (st.nextToken() != StreamTokenizer.TT_EOF) {
            int n = (int) st.nval;
            st.nextToken();
            int k = (int) st.nval;
            int array[] = new int[n];
            for (int i = 0; i < n; i++) {
                st.nextToken();
                array[i] = (int) st.nval;
            }
            int low = 0 ;
            int high = n - 1;
            while (low < high) {
                if (array[low] + array[high] > k) {
                    high -- ;
                }else if (array[low] + array[high] < k) {
                    low ++;
                }else {
                    break;
                }
            }
            if( low < high ){
                System.out.println(array[low]+" "+array[high]);
            }else {
                System.out.println("-1 -1");
            }
        }
    }
}
/**************************************************************
    Problem: 1352
    User: wzqwsrf
    Language: Java
    Result: Accepted
    Time:3290 ms
    Memory:30608 kb
****************************************************************/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值