[LeetCode]nsum问题集合

本文介绍了LeetCode上的nSum系列问题,包括Two Sum、3Sum、3Sum Closest和4Sum的解题方法。通过排序和双指针技巧,解决这些寻找特定和的子数组问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

nsum问题是面试中经常会问到的题目,LeetCode上关于nsum的问题有

 

这里将介绍这四个问题的解答方法,

Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,

return [0, 1].

————————

这道题直接用两个循环暴力解即可,对数组进行遍历查找两个数之和,时间复杂度是O(n^2),在题目允许范围内

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int tsum[]=new int[2];
        for(int i=0;i<nums.length-1;i++)
        {
            for(int j=i+1;j<nums.length;j++)
            {
                if((nums[i]+nums[j])==target)
                {
                    tsum[0]=i;
                    tsum[1]=j;
                    return tsum;
                }
            }
        }
        return tsum;
    }
}

3Sum

Given an array nums of n integers, are there elements abc in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:

[

[-1, 0, 1],

[-1, -1, 2]

]

—————————

这道题暴力解的话时间复杂度是O(n^3),一般情况下肯定会超时的,所以这里对题目分析一下,如果降低时间复杂度。

当然,在对数组题没有什么思路的情况下,在题目对顺序没有要求的话,可以先将数组进行排序,方便之后的操作。对这道题的数组先排序。

Arrays.sort(nums);

同样,我们可以把这个问题转化为2sum的问题,但是外层循环每一次查找的target变成了需要计算的总值(这里是0)减去数组中的每个数,即为

target=0-nums[i]

这里需要注意的是,如果数组中存在两个相等的值,那如果对这两个值都进行查找,得到的结果肯定是相同的,为了避免这种情况,应该加入判断语句

if(i>0&&nums[i]==nums[i-1])
        {
            continue;
        }

内层循环查找的方式为从两端向中间查找,不断逼近所需的target,当两端数之和小于target时,即

nums[left]+nums[right]+nums[i]<0

此时需要将left++,使得更接近target。

反之如果大于target,需要将right--.

如果等于的话则存入输出的List中,同时将left和right向中间移动。这里还需要判断如果移动到了相同的left/right的值,为了避免得到重复的结果,应该继续移动。

while(left<right&&nums[left]==nums[left-1])
{
		left++;
}
while(left<right&&nums[right]==nums[right+1])
{
		right--;
}

因此可以得到如下结果:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        	Arrays.sort(nums);
	        List<List<Integer>> lsi=new ArrayList<>();
	        for(int i=0;i<nums.length-2;i++)
	        {
                if(i>0&&nums[i]==nums[i-1])
	        	{
	        		continue;
	        	}
	        	int target=-nums[i];
	        	int left=i+1,right=nums.length-1;
	        	while(left<right)
	        	{
	        		if(nums[left]+nums[right]<target)
	        		{
	        			left++;
	        		}
	        		else if(nums[left]+nums[right]>target)
	        		{
	        			right--;
	        		}
	        		else 
	        		{
	        			List<Integer> tar=Arrays.asList(-target,nums[left],nums[right]);
	        			lsi.add(tar);
	        			left++;
	        			right--;
	        			while(left<right&&nums[left]==nums[left-1])
		        		{
		        			left++;
		        		}
		        		while(left<right&&nums[right]==nums[right+1])
		        		{
		        			right--;
		        		}
	        		}
	        	}
	        }
	        return lsi;
    }
}

3Sum Closest

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

题目的意思就是,给出一个数组和一个目标值,需要找到3个数,使它们之和最接近这个目标值,并返回这个和。

解题和3Sum差不多,需要注意的只有设置一个变量mm来记录结果,在循环中如果得到的和不等于target,则判断其与mm谁更接近,mm则改为更接近的那个值。

class Solution {
    public int threeSumClosest(int[] nums, int target) {
	        Arrays.sort(nums);
	        int mm=nums[0]+nums[1]+nums[nums.length-1];
	        for(int i=0;i<nums.length-2;i++)
	        {
	        	if(i>0&&nums[i]==nums[i-1])
	        	{
	        		continue;
	        	}
	        	int targ=target-nums[i];
	        	int left=i+1,right=nums.length-1;
	        	while(left<right)
	        	{
	        		if(nums[left]+nums[right]<targ)
	        		{
	        			if(Math.abs(mm-target)>Math.abs(nums[left]+nums[right]+nums[i]-target))
	        			{
	        				mm=nums[left]+nums[right]+nums[i];
	        			}
	        			left++;
	        		}
	        		else if(nums[left]+nums[right]>targ)
	        		{
	        			if(Math.abs(mm-target)>Math.abs(nums[left]+nums[right]+nums[i]-target))
	        			{
	        				mm=nums[left]+nums[right]+nums[i];
	        			}
	        			right--;
	        		}
	        		else 
	        		{
	        			return target;
	        		}
	        		
	        	}
	        }
	        return mm;
    }
}

4Sum

Given an array nums of n integers and an integer target, are there elements abc, and d in nums such that a + b + c + dtarget? Find all unique quadruplets in the array which gives the sum of target.

Note:

The solution set must not contain duplicate quadruplets.

Example:

Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:

[

    [-1,  0, 0, 1],

    [-2, -1, 1, 2], 

    [-2,  0, 0, 2]

]

同样,我们可以参考3Sum的方法,3Sum是先确定3个数中的1个数,这里利用两层循环确定4个数中的2个数,同时需要考虑重复的情况(这个比较坑)

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
            Arrays.sort(nums);
	        List<List<Integer>> lsi=new ArrayList<>();
	        for(int i=0;i<nums.length-3;i++)
	        {
	        	
	        	for(int j=i+1;j<nums.length-2;j++)
	        	{
                    
		        	int ta=target-nums[i]-nums[j];
		        	int left=j+1,right=nums.length-1;
		        	while(left<right)
		        	{
		        		if(nums[left]+nums[right]<ta)
		        		{
		        			left++;
		        		}
		        		else if(nums[left]+nums[right]>ta)
		        		{
		        			right--;
		        		}
		        		else 
		        		{
		        			List<Integer> tar=Arrays.asList(nums[i],nums[j],nums[left],nums[right]);
		        			lsi.add(tar);
		        			left++;
		        			right--;
		        			while(left<right&&nums[left]==nums[left-1])
			        		{
			        			left++;
			        		}
			        		while(left<right&&nums[right]==nums[right+1])
			        		{
			        			right--;
			        		}
			        		while(i<nums.length-4&&nums[i]==nums[i+1])
				        	{
				        		i++;
				        	}
			        		while(j<nums.length-3&&nums[j]==nums[j+1])
		                    {
		                        j++;
		                    }
		        		}
		        	}
	        	}
                
	        }
	        return lsi;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值