• 4Sum——LeetCode


    这是我刷题时,在观看solutions时看到的方法,此方法时间复杂度为o(n^3) 空间复杂度为o(1)。此方法思想最大优点是,可以将其运用到所有关于KSum这类算法中。

    Talk ischeap, Show me the code.

    public List<List<Integer>> fourSum(int[] nums, int target) {
    		ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
    		int len = nums.length;
    		if (nums == null || len < 4)
    			return res;
    		//首先对数组排序
    		Arrays.sort(nums);
    
    		int max = nums[len - 1];
    		if (4 * nums[0] > target || 4 * max < target)
    			return res;
    
    		int i;
    		int z;
    		for (i = 0; i < len; i++) {
    			z = nums[i];
    			//已经找过的数就没必要继续找了,避免重复
    			if (i > 0 && z == nums[i - 1])
    				continue;
    			//z不能太小
    			if (z + 3 * max < target)
    				continue;
    			//z不能太大
    			if (4 * z > target) 
    				break;
    			//如果z刚好是平均数的话
    			if (4 * z == target) { 
    				if (i + 3 < len && nums[i + 3] == z)
    					res.add(Arrays.asList(z, z, z, z));
    				//因为z下面的数肯定比z大,就没必要继续找了
    				break;
    			}
    			//找到的z绝对是四个数中最小的
    			//找到第一个数后,继续找下一个数
    			threeSumForFourSum(nums, target - z, i + 1, len - 1, res, z);
    		}
    
    		return res;
    	}
    
    	//找剩下3个数中的最小的那个数,
    	public void threeSumForFourSum(int[] nums, int target, int low, int high, ArrayList<List<Integer>> fourSumList,
    			int z1) {
    		if (low + 1 >= high)
    			return;
    
    		int max = nums[high];
    		if (3 * nums[low] > target || 3 * max < target)
    			return;
    
    		int i;
    		int z;
    		for (i = low; i < high - 1; i++) {
    			z = nums[i];
    			if (i > low && z == nums[i - 1])
    				continue;
    			if (z + 2 * max < target)
    				continue;
    
    			if (3 * z > target)
    				break;
    
    			if (3 * z == target) {
    				if (i + 1 < high && nums[i + 2] == z)
    					fourSumList.add(Arrays.asList(z1, z, z, z));
    				break;
    			}
    			//找到四个数中的第二大的数,接着去找剩下的两个数
    			twoSumForFourSum(nums, target - z, i + 1, high, fourSumList, z1, z);
    		}
    
    	}
    
    	
    	//两个指针遍历剩下的数组
    	public void twoSumForFourSum(int[] nums, int target, int low, int high, ArrayList<List<Integer>> fourSumList,
    			int z1, int z2) {
    
    		if (low >= high)
    			return;
    
    		if (2 * nums[low] > target || 2 * nums[high] < target)
    			return;
    
    		int i = low;
    		int j = high;
    		int sum = 0;
    		int x = 0;
    		while (i < j) {
    			sum = nums[i] + nums[j];
    			if (sum == target) {
    				fourSumList.add(Arrays.asList(z1, z2, nums[i], nums[j]));
    
    				x = nums[i];
    				//跳过相同的数
    				while (++i < j && x == nums[i]) 
    					;
    				x = nums[j];
    				while (i < --j && x == nums[j])
    					;
    			}
    			if (sum < target)
    				i++;
    			if (sum > target)
    				j--;
    		}
    		return;
    	}


  • 相关阅读:
    多线程间通信之AutoResetEvent和ManualResetEvent的原理分析和开发示例
    【推荐】基于WebActivator的改进版本KudyStudio.Web.Activating讲解与源码下载
    Visual Studio中你所不知道的智能感知
    压缩网页图片
    二叉树
    DynamicXml 动态读取操作XML (一个从XML到Object的通用实现)
    张剑微软2011 GCR MVP Open Day 之旅!【转载】
    使用Solr构建企业级的全文检索
    jQuery版仿Path菜单发布!
    使用maven进行开发过程管理之准备篇
  • 原文地址:https://www.cnblogs.com/loren-Yang/p/7466142.html
Copyright © 2020-2023  润新知