zoukankan      html  css  js  c++  java
  • 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;
    	}


  • 相关阅读:
    利用余数选择特殊位置元素
    CSS hack
    css选择器
    按yyyy-mm-dd格式输入一个日期,判断这是这一年的第几天
    输入不同year,month,打印月历
    java学习之多线程(二)
    java学习之多线程
    剑指offer--第一个只出现一次的字符
    剑指offer--两个链表的第一个公共结点
    剑指offer--最小的k个数
  • 原文地址:https://www.cnblogs.com/loren-Yang/p/7466142.html
Copyright © 2011-2022 走看看