• 3sum


    描述:

    给定一个整形无序数组a,其中元素可重复,在a中找出所有的{a, b, c}满足条件a+b+c=0,且结果不可以重复

    例如,给定数组S = [-1,0,1,2,-1,-4],
    
    答案:
    [
      [-1,0,1],
      [-1,-1,2]
    ]
    

    思考过程:

    在解决这个题时,我一直考虑怎么才能避免重复,因为这是个无序数组,我最先想到的是匹配已有结果,但是这样会超级复杂,解决方法一定不是这样的。那么既然无序的不好办,把它变成有序的如何?ok就是这样。用Arrays.sort(a),就可以让数组有序化。

    本着先做出来再注意时间复杂度的想法,下面是我的方法,逻辑正确,时间超限制了:

    public static List<List<Integer>> threeSum(int[] nums) {
    	        Arrays.sort(nums);
    	        List<List<Integer>> results = new ArrayList();
    	        int a,b,c,l=nums.length;
    	        for(int i=0; i<l-2; i++){
    	            a=nums[i];
    	            for(int j=i+1; j<l-1; j++){
    	                b=nums[j];
    	                for(int n=j+1; n<l; n++){
    	                    c=nums[n];
    	                    //由于nums是顺序的,所以当c>(0-a-b)条件满足时且还未匹配到结果时,此次第三层循环就不会有结果了,直接break
    	                    if(c>(0-a-b))
    	                        break;
    	                    if(a+b+c == 0){
    	                        List<Integer> result = new ArrayList();
    	                        result.add(a);
    	                        result.add(b);
    	                        result.add(c);
    	                        results.add(result);
    	                        break;
    	                    }
    	                }
    	                //避免第二个数重复出现
    	                while((j+1<l-1) && (b == nums[j+1])){
    	                    j++;
    	                }
    	            }
    	            //避免第一个数重复出现
    	            while((i+1<l-2) && (a == nums[i+1])){
    	                    i++;
    	            }
    	        }
    	        return results;
    	    }
    

    下面是leetcode大神的方法:

    public List<List<Integer>> threeSum1(int[] num) {
    		    Arrays.sort(num);
    		    List<List<Integer>> res = new LinkedList<>(); 
    		    //这里计算的是第一个数,第一个数是从第0位到第length-2位
    		    for (int i = 0; i < num.length-2; i++) {
    		    	
    		    	//当i++时要避免num[i]=num[i++],否则会出现重复的集合
    		        if (i == 0 || (i > 0 && num[i] != num[i-1])) {
    		        	
    		        	//计算出了第二位数的循环区间(lo,hi)和第二第三位数的加和sum
    		            int lo = i+1, hi = num.length-1, sum = 0 - num[i];
    		            
    		            //这里计算的是第二个数,第二个数每次都要在第一位数的后一位开始,即i+1位到第length-1位
    		            //循环里做的事情是:当第一位数一定时,找出所有可能的第二和第三位数
    		            while (lo < hi) {
    		            	
    		            	//当第二个和第三个数符合题目条件时,那么上下线都应该同时移动
    		                if (num[lo] + num[hi] == sum) {
    		                    res.add(Arrays.asList(num[i], num[lo], num[hi]));
    		                  //两个while功能是避免第二和第三个数的重复出现
    		                    while (lo < hi && num[lo] == num[lo+1]) lo++;
    		                    while (lo < hi && num[hi] == num[hi-1]) hi--;
    		                    lo++; hi--;
    		                } 
    		              //如果不符合条件,就应该按照实际情况只移动上限或者下限
    		                else if (num[lo] + num[hi] < sum)   
    		                	lo++;
    		                else hi--;
    		           }
    		        }
    		    }
    		    return res;
    		}
    

      

  • 相关阅读:
    创建分区表(按照年份分区,自动新增分区)
    flash rock me
    苹果有虫才好吃
    Evolutility改造支持oracle
    Nhibernate问题三则
    Html5+razor+jqmobile尝鲜
    配置Instantclient
    T4,Redmine,Nhibernate etc
    monotouch开发ios应用手记
    大文件及文件夹上传(续)
  • 原文地址:https://www.cnblogs.com/K-artorias/p/7909071.html
Copyright © 2020-2023  润新知