N-SUM

"N, Sum"

Posted by shihunyewu on June 11, 2018

数组中 n 个数的和为 0 问题

1. Two Sum

给定一组数,找出其中和为 0 的两个数,很简单的想法,使用 HashMap,键为数组元素,值为数组索引。遍历数组,赋值,同时检测数据元素的相反数是否包含在 map 中,如果包含,得到其索引,然后返回

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
        int rArray[] = new int[2];
        for(int i = 0;i<nums.length;i++){
            Integer anotherIndex = map.get(target - nums[i]);
            if(anotherIndex !=null && anotherIndex != i){
                rArray[0] = anotherIndex;
                rArray[1] = i;
                return rArray;
            }
            map.put(nums[i],i);
        }
        return null;
    }
}

15. 3Sum

给定一组数,找出其中和为 0 的三个数。

public class Solution {
    List<List<Integer>> ret = new ArrayList<List<Integer>>();

    public List<List<Integer>> threeSum(int[] num) {
      if(num == null || num.length < 3) return ret;
      Arrays.sort(num);
      int len = num.length;
      for(int i = 0; i < len-2; i++){
          if(num[i] > 0){
              break;
          }
          if(i > 0 && num[i] == num[i-1]) continue;
          find(num, i+1, len-1, num[i]);
      }
      return ret;
    }

    public void find(int[] num, int begin, int end, int target){
      int l = begin;
      int r = end;
      while(l < r){
        if(num[l] + num[r] + target == 0){
          List<Integer> ans = new ArrayList<Integer>();
          ans.add(target);
          ans.add(num[l]);
          ans.add(num[r]);
          ret.add(ans);
          while(l < r && num[l] == num[l + 1]) l++; //为了防止重复,遇见相同的就直接跳过
          while(l < r && num[r] == num[r - 1]) r--;
          l++;
          r--;
        } else if(num[l] + num[r] + target < 0){
          l++;
        } else{
          r--;
        }
      }
    }
}
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> ll = new ArrayList<List<Integer>>();
        Arrays.sort(nums);
        for(int i = 0;i< nums.length; i++ )
        {
           if(i > 0 && nums[i] == nums[i-1])
               continue;
            List<Set<Integer>> rls = twoSum(nums, -nums[i], i, i); // 缩减时间复杂度的关键?
            for(Set<Integer> rl: rls){
                    List<Integer> nl = new ArrayList(rl);
                    if(rl.size()<3){ // 因为 set 类型中不能有重复数据,因此例如 2,2-4 这种组合最终会变成 2,-4
                        int temp = 0;
                        for(Integer elem:nl){
                            temp = temp - elem;
                        }
                        nl.add(temp);
                        if(temp == 0) // 因为 set 类型中不能有重复元素,因此例如 0,0,0 这种组合会变成 0
                            nl.add(0);
                    }
                    ll.add(nl);
            }
        }
        return ll;
    }

    public List<Set<Integer>> twoSum(int[] nums, int target, int j, int start){ 
        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
        List<Set<Integer>> rls = new ArrayList<Set<Integer>>();
        for(int i = start;i<nums.length;i++){
            if(i == j) // 一旦遇到 target 元素所在位置,跳过本次循环
                continue;
            Integer anotherIndex = map.get(target - nums[i]);
            if(anotherIndex !=null && anotherIndex != i ){
                Set<Integer> temps = new HashSet<Integer>();
                temps.add(nums[anotherIndex]);
                temps.add(nums[i]);
                temps.add(-target);
                if(!rls.contains(temps)){
                    rls.add(temps);
                }
            }
            map.put(nums[i],i); // 将 nums[i] 和 i 映射添加到 map 中,防止重合
        }

        return rls;
    }
}