编程题:两数之和&数组中相加为0的三元数组

两数之和

给出一个整数数组,请在数组中找出两个加起来等于目标值的数,
你给出的函数twoSum 需要返回这两个数字的下标(index1,index2),需要满足 index1 小于index2.。注意:下标是从1开始的
假设给出的数组中只存在唯一解
例如:

给出的数组为 {20, 70, 110, 150},目标值为90
输出 index1=1, index2=2

数组中相加为0的三元数组

给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。
注意:
  1. 三元组(a、b、c)中的元素必须按非降序排列。(即a≤b≤c)
  2. 解集中不能包含重复的三元组。
例如,给定的数组 S = {-10 0 10 20 -10 -40},解集为(-10, 0, 10) (-10, -10, 20)

思路

  之所以将两道题目放在一起讲,主要时因为当初这两道题给了我很强的既视感,两个题目解题思路相互影响,导致了我走向了两个错误的方向,每一道题都走错了。

  两数之和:第一反应是排序遍历,因为求和排序后会方便遍历,然而该题目需要返回的是下标,排序打乱顺序会影响结果,如果强行实现也会多出许多用来记录原位置的开销。那么放弃了排序的算法,使用map以记录(数值,下标),每次遍历前判断是否存在target-当前值的值在map中,有则取出并返回下标。

  数组中相加为0的三元组:做到这个题的时候刚做完两数之和,脑子一下子没转过来,a+b+c=0不就是a+b=-c吗?然而这个题目不是唯一解,而且需要返回对的是三元组按非降序排列,而且不允许重复。所以排序后再遍历是一个很好的方法。

解题:两数之和

/**
     *
     * @param numbers int整型一维数组
     * @param target int整型
     * @return int整型一维数组
     */
    public int[] twoSum (int[] numbers, int target) {
        /*从数组中返回和是targe的两个数的下标,假设有值且唯一,下标从1起算*/
        Map<Integer,Integer> map= new HashMap<>();
        //PrintIntArray(numbers);
        for(int i=0;i<numbers.length;i++){
            if(map.containsKey(target-numbers[i])){
                return new int[]{map.get(target-numbers[i])+1,i+1};
            }
            map.put(numbers[i],i);
        }
        return new int[]{-1,-1};
    }

解题:数组中相加为0的三元数组

    public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
       ArrayList<ArrayList<Integer>> res = new ArrayList<>();
       /*先排序*/
        sort(num);
        for(int i=0;i<num.length;){
            if(num[i]>0) break; //优化
            for(int j=i+1;j<num.length;){
                if(num[i]+num[j]>0) break;
                for(int k=j+1;k<num.length;){
                    if(num[i]+num[j]+num[k]>0){
                        break; //优化
                    }
                    if(num[i]+num[j]+num[k]==0){
                        ArrayList<Integer> alist = new ArrayList<>();
                        alist.add(num[i]);
                        alist.add(num[j]);
                        alist.add(num[k]);
                        res.add(alist);
                        break;
                    }
                    int temp = num[k];
                    while (k<num.length&&num[k]==temp){//跳过重复项
                        k++;
                    }
                }
                int temp = num[j];
                while (j<num.length&&num[j]==temp){//跳过重复项
                    j++;
                }
            }
            int temp = num[i];
            while (i<num.length&&num[i]==temp){//跳过重复项
                i++;
            }
        }
       return res;

    }
当你深入了解,你就会发现世界如此广袤,而你对世界的了解则是如此浅薄,请永远保持谦卑的态度。
原文地址:https://www.cnblogs.com/liwxmyself/p/14699245.html