leetcode 2sum,3sum,4sum总结

2sum问题,给定一个数组,一个确定的数target,在该数组中寻找两个数使得其和等于target,并返回这两个数在数组中的索引。(题目假设只有一个解的情况下实际上多个解也是可以完成的,只需要开一个装vector<int>的vector,然后把每次符合条件的vectorpush进去就好了)

两个for循环,搞定,代码如下(C++):

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
         for(int i=0;i<nums.size();i++)
        {
            for(int j=i+1;j<nums.size();j++)
            {
                if(nums[i]+nums[j]==target){
                    return vector<int>{i,j};
                }
            }
        }
    }

};

这是我脑子里最先想到的想法,后来看别人写的博客,发现还有其他的优化方法。我找的这个博主的想法是:先把给定的数组排序(排序之前先把这个数组复制一份,便于最后根据数据找索引),设定两个指针,一个指向头部,一个指向尾部,然后利用局部逼近的原则,如果求和比target大,则尾部指针往前跳,=target,跳出循环,<target,头部指针往后跳。JS代码如下:

 

var twoSum = function(nums, target) {  
    var temp = nums.slice(0);  //上述的复制数组的作用
    nums = nums.sort(function(a,b){return a-b;});  
    var i = 0;  
    var j = nums.length - 1;  
    while(nums[i] + nums[j] != target){  
        if(nums[i] + nums[j] > target){  
            j--;  
        }else{  
            i++;  
        }  
    }   
    i = temp.indexOf(nums[i]);   
    j = temp.lastIndexOf(nums[j]);  
    var index = new Array(i, j);    
    index = index.sort(function(a,b){return a-b;});  
    return index;  

}; 

 

3sum问题:给定一个数组,找出三个数a,b,c使得a+b+c=0,返回所有的满足情况的a,b,c的组合,不能重复。

 

暴力不可取,不能利用三个for来解决问题吧,而且这样做还是不能避免重复的问题。

思路:(这个时候就可以随便排序了,我们需要的是数而跟数的索引无关)首先排序,然后用一个for循环遍历,遍历到的数据记为第i个,用两个指针分别指向i+1和length-1,与2sum相同,三数求和之后与0作比较,在pleft<pright的情况下根据与target的比较依次移动指针,满足条件则push进容器里面。实际还是转换了一下转化为2sum问题,先固定一个数,也就是所说的i,再一次移动两个指针,也就是2sum问题。代码如下(JAVA):

class Solution {
public List<List<Integer>> threeSum(int[] nums) {

    List<List<Integer>> result = new ArrayList<List<Integer>>();

 

 //处理不满足题意的情况
    if(nums == null || nums.length<3)

        return result;

 

 //排序

    Arrays.sort(nums);

 

 //实现遍历,固定一个数i
    for(int i=0; i<nums.length-2; i++){
        if(i==0 || nums[i] > nums[i-1]){
            int j=i+1;//pleft指针
            int k=nums.length-1;//pright指针
 

            while(j<k){

            //如果满足条件,则添加进去

                if(nums[i]+nums[j]+nums[k]==0){
                    List<Integer> l = new ArrayList<Integer>();
                    l.add(nums[i]);
                    l.add(nums[j]);
                    l.add(nums[k]);
                    result.add(l);

                     //此时需要同时移动两个指针

                    j++;
                    k--;
 
                    //消除重复
                    while(j<k && nums[j]==nums[j-1])
                        j++;
                    while(j<k && nums[k]==nums[k+1])
                        k--;
 

                }

                //处理小于的情况,移动pleft

                else if(nums[i]+nums[j]+nums[k]<0){

                    j++;

                }

                //处理大于的情况,移动pright指针

                else{

                    k--;
                }
            }
        }
 
    }
 
    return result;
}
}

4sum问题:给定一个数组,在该数组中找到a,b,c,d四个数,使得a+b+c+d=target,返回所有的这四个数的组合,不允许重复。同3sum,转换为2sum一样,也要逐一实现把4sum转换为3sum再转换为3sum来解决这个问题。首先老规矩,排序,然后在设定两个指针,固定两个数,然后再设定两个指针,移动指针来找到4个满足条件的数,其间涉及到去重问题。代码如下(JAVA):

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {

               List<List<Integer>> lists=new ArrayList<List<Integer>>();

        //处理不满足题目条件时候的情况

        if (nums.length<4){
            return lists;
        }

        //进行数组排序
        Arrays.sort(nums);
        for (int i=0;i<nums.length-3;i++){
            
            if(i>0&&nums[i]==nums[i-1]){
                continue;
            }
            
            //固定两个数i和j,用两个移动的数start和end来遍历数组(i为主要固定者,j为次要固定者)
            for (int j=i+1;j<nums.length-2;j++){
                int start = j+1;
                int end = nums.length-1;
                
                
                while (start<end){
                    int sum = nums[i]+nums[j]+nums[start]+nums[end];
                    if (sum==target){
                       List<Integer> newlist= Arrays.asList(nums[i], nums[j], nums[start], nums[end]);
                       if (!lists.contains(newlist)){
                           lists.add(newlist);
                       }
                        start++;
                        end--;
                    }
                    else if(sum<target){
                        start++;
                    }
                    else 
                    {
                        end--;
                    }
                }


            }


        }
        return lists;
    }
}

简单总结了一下,便于以后快速回顾

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值