问题描述:

  从一些数中取出四个,使和等于N,可任意重复取,求所有的情况。 与以下题目相似

  http://oj.leetcode.com/problems/4sum/

解题思路:

  •   暴力解法(四重循环),效率很低

  •   利用hash的方法:先将数据两两相加,将和作为key,将两个数据组成的集合作为值value;由于相同的和值的组合可能有多个,所以 value应该是一个多种组合的集合。以下是我的一种实现,个人感觉代码不够简洁,但一时没有找到优化思路,先贴到这里,希望将来能够找到更好的方法,也希望有人看到问题的话能够指正出来

  •  其他解决方法,比如:动态规划

    hash方法的代码如下:

     

    public class Solution {
        public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) { 
            ArrayList<ArrayList<Integer>> arrlist = new ArrayList<ArrayList<Integer>>();
            //为了去重
            Set<ArrayList<Integer>> finalsetlist = new HashSet<ArrayList<Integer>>();
            int len =num.length;
            if(len<4){
                return null;
            }
            //先排序
            int[] numtemp = sort(num);
            System.out.print("排序之后:");
            for(int nu:numtemp){           
                System.out.print(nu+" ");
            }
            System.out.println();
            //判断最大的四个数是否大于target
            int maxlastfour =0;
            //判断最小的四个数是否小于target
            int minfirstfour =0;
            for(int i=len-1;i>len-5;i--){
                maxlastfour +=numtemp[i];
            }
            System.out.println("最大的四个数之和:"+maxlastfour);
            if(maxlastfour<target){
                return null;
            }
            for(int i=0;i<4;i++){
                minfirstfour += numtemp[i];
            }
            System.out.println("最小的四个数之和:"+minfirstfour);
            if(minfirstfour>target){
                return null;
            }
            //利用hash原理,先计算两个数的和
            Map<Integer,Set<List<Integer>>> map = new HashMap<Integer,Set<List<Integer>>>();
            //将每两个数相加,和为key,这两个数的组合为value,考虑到和等于target的组合有多种,用set集合保存各种组合可能
            for(int i=0;i<numtemp.length;i++){
                for(int j=0;j<numtemp.length;j++){
                    Set<List<Integer>> set =null;
                    int key = numtemp[i]+numtemp[j];
                    if(!map.containsKey(key)){
                        set = new HashSet<List<Integer>>();
                         List<Integer> list = new ArrayList<Integer>();
                         list.add(numtemp[i]);
                         list.add(numtemp[j]);
                         set.add(list);
                         map.put(key,set);
                    }else{
                         set = map.get(key);
                         List<Integer> list = new ArrayList<Integer>();
                         list.add(numtemp[i]);
                         list.add(numtemp[j]);
                         set.add(list);
                         map.put(key,set);
                    }
                }
            }
            //排序以后
            Map<Integer,Set<List<Integer>>> mapresult = new HashMap<Integer,Set<List<Integer>>>();
            List<Map.Entry<Integer, Set<List<Integer>>>> maplist = new ArrayList<Map.Entry<Integer, Set<List<Integer>>>>(map.entrySet());
            Collections.sort(maplist,new Comparator<Map.Entry<Integer,Set<List<Integer>>>>(){
                public int compare(Map.Entry<Integer,Set<List<Integer>>> map1,Map.Entry<Integer,Set<List<Integer>>> map2){
                    return map1.getKey().compareTo(map2.getKey());
                }
            });    
            for(Map.Entry<Integer,Set<List<Integer>>> mapen:maplist){
                mapresult.put(mapen.getKey(), mapen.getValue());
            }
            //从hash表中查找是否存在这样的组合
            Set<Integer> keys = mapresult.keySet();
            for(Integer k:keys){
                int firtwo = k;
                Set<List<Integer>> setvaluefir = mapresult.get(firtwo);
                int sectwo = target-firtwo;
                Set<List<Integer>> setvaluelas = mapresult.get(sectwo);
                if((mapresult.get(Integer.valueOf(sectwo))!=null)&&(mapresult.get(Integer.valueOf(sectwo)).size()>0)){
                    for(List<Integer> listvalue:setvaluefir){
                        for(List<Integer> listvalue1:setvaluelas){                       
                            ArrayList<Integer> arr = new ArrayList<Integer>();
                            arr.addAll(listvalue);
                            arr.addAll(listvalue1);
                            //按升序输出
                            Collections.sort(arr);
                            finalsetlist.add(arr);
                            //arrlist.add(arr);
                        }
                    }
                }
            }
            for(ArrayList<Integer> arrli:finalsetlist){
                arrlist.add(arrli);
            }
            return arrlist;
        }
        //排序
        public int[] sort(int[] num){
              int[] numtemp = num;
              int numlen = numtemp.length;
              for(int i=0;i<numlen;i++){
                  for(int j=i;j<numlen;j++){
                      if(numtemp[i]>numtemp[j]){
                          int temp = numtemp[i];
                          numtemp[i] = numtemp[j];
                          numtemp[j] =temp;
                      }
                  }
              }
              return numtemp;
        }
    }