【LeetCode 15 18 16】三数与四数之和,最接近的三数之和

第15题

 从时间复杂度上看,和双指针相同,甚至高于双指针,但是计算时间上快了很多。。。

	public static List<List<Integer>> threeSum(int[] nums) {
    
    
		List<List<Integer>> ret = new ArrayList<List<Integer>>();
		Arrays.sort(nums);
		for (int i = 0; i < nums.length; i++)
		{
    
    
			if (i ==0 || nums[i] != nums[i-1]) // 保证前后两次循环的数字不同
			{
    
    
				int k = nums.length - 1;
				for (int j = i+1; j < nums.length-1; j++) // 第三个数字是k表示的
				{
    
    
					if (j == i+1 || nums[j] != nums[j-1]) // 保证前后两次循环的数字不同
					{
    
    
						while (k > j && nums[i] + nums[j] + nums[k] > 0) // 第三个数字和第二个数字不能相等
						{
    
    
							k--; // 第三个数字向左移动,和变小
						}
						if (nums[i] + nums[j] + nums[k] == 0)
						{
    
    
							List<Integer> l = Arrays.asList(i, j, k);
							ret.add(l);
						}
					}
				}
			}
		}
		return ret;
	}

第15题,使用双指针,时间复杂度为O(n2)

	public static List<List<Integer>> threeSum2(int[] nums) {
    
    
		List<List<Integer>> ret = new ArrayList<List<Integer>>();
		Set<List<Integer>> set = new HashSet<List<Integer>>();
		Arrays.sort(nums);
		for (int i = 0; i < nums.length-2; i++)
		{
    
    
			int j = i+1;
			int k = nums.length-1;
			int sum;
			while (j < k)
			{
    
    
				sum = nums[i] + nums[j] + nums[k];
				if (sum < 0)
					j++;
				else if (sum > 0)
					k--;
				else 
				{
    
    
					List<Integer> l = Arrays.asList(nums[i], nums[j], nums[k]);
					set.add(l); // 有重复的问题
					j++;
					k--;
				}
			}
		}
		ret.addAll(set);
		return ret;
	}

第16题

    public static int threeSumClosest(int[] nums, int target) {
    
    
    	int ret = 0;
    	int[] pos = new int[3];
    	int d = Integer.MAX_VALUE; // 目的是使得d逐渐减小,全局的最小
    	Arrays.sort(nums);
    	for (int i = 0; i < nums.length; i++)
    	{
    
    
    		if (i == 0 || nums[i] != nums[i-1])
    		{
    
    
    			for (int j = i+1; j < nums.length-1; j++)
    			{
    
    
    				if (j == i+1 || nums[j] != nums[j-1])
    				{
    
    
						int n = target - nums[i] - nums[j]; 
						int k = nums.length-1;
						int dd = Integer.MAX_VALUE;
						while (k > j)
						{
    
    
							if (Math.abs(nums[k] - n) <= dd) // dd 是指当前的距离,而不是全局的距离
							{
    
    
								dd = Math.abs(nums[k] - n);
								if (dd <= d)
								{
    
    
									d = dd;
									pos[0] = i;
									pos[1] = j;
									pos[2] = k;
								}
							}
							else // 差距更大了,就可以退出了
								break; // 一旦差距变大,后面数字的差距也会越来越大
							k--;
						}
    				}
    			}
    		}
    	}
    	ret = nums[pos[0]] + nums[pos[1]] + nums[pos[2]];
    	return ret;
    }

第16题,使用双指针,时间复杂度为O(n2)

   public static int threeSumClosest(int[] nums, int target) {
    
    
    	int ret = 0;
		Arrays.sort(nums);
		int[] pos = new int[3];
		int dist = Integer.MAX_VALUE;
		for (int i = 0; i < nums.length-2; i++)
		{
    
    
			int j = i+1;
			int k = nums.length-1;
			// 以距离更近更远为标准判断如何移动左右指针。
			int sum;
			while (j < k)
			{
    
    
				sum = nums[i] + nums[j] + nums[k];
				if (sum < target) // 判断向哪个方向移动 
				{
    
    
					if (target - sum < dist) // 判断何时更新
					{
    
    
						dist = target - sum; // 更新部分,可以写成一个update();
						pos[0] = i;
						pos[1] = j;
						pos[2] = k;
					}
					j++;
				}
				else if (sum > target)
				{
    
    
					if (sum - target < dist)
					{
    
    
						dist = sum - target; // 更新部分,可以写成一个update();
						pos[0] = i;
						pos[1] = j;
						pos[2] = k;
					}
					k--;
				}
				else // sum == target 
                    return nums[i] + nums[j] + nums[k];
			}
		}
		ret = nums[pos[0]] + nums[pos[1]] + nums[pos[2]];
		return ret;
    }

第18题

    public static List<List<Integer>> fourSum(int[] nums, int target) {
    
    
    	List<List<Integer>> ret = new ArrayList<List<Integer>>();
    	Arrays.sort(nums);
    	for (int i = 0; i < nums.length; i++)
    	{
    
    
    		if (i == 0 || nums[i] != nums[i-1])
    		{
    
    
    			for (int j = i+1; j < nums.length-2; j++)
    			{
    
    
    				if (j == i+1 || nums[j] != nums[j-1])
    				{
    
    
    					for (int k = j+1; k < nums.length-1; k++)
    					{
    
    
    						int l = nums.length-1;
    						while (l > k && nums[i] + nums[j] + nums[k] + nums[l] > target)
    							l--;
    						if (l > k && nums[i] + nums[j] + nums[k] + nums[l] == target)
    						{
    
    
    							List<Integer> ll = Arrays.asList(nums[i], nums[j], nums[k], nums[l]);
    							ret.add(ll);
    						}
    							
    					}
    				}
    			}
    		}
    	}
    	return ret;
    }

Supongo que te gusta

Origin blog.csdn.net/juttajry/article/details/121510958
Recomendado
Clasificación