数组—— 2 sum, 3 sum, 3 sum closed, 4Sum.

题目一:2 sum      找两数之和为target的下标。

hashmap 当哈希表中不存在当前i的数字target-numbers[i]时,将(numbers[i],i)put入表;找到则返回。

import java.util.*;
public class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int[] index=new int[2];
        if(numbers == null||numbers.length<2)
            return index;
        Map<Integer,Integer> map=new HashMap();
        map.put(numbers[0],0);
        for(int i=1;i<numbers.length;i++)
            {
            if(map.containsKey(target-numbers[i]))
                {
                index[0]=map.get(target-numbers[i])+1;
                index[1]=i+1;
            }
            else
                {
                map.put(numbers[i],i);
            }
        }
        return index;
    }
}

若题目要求为保存数值,也可排序后使用双下标从两端查找。

 public int[] twoSum(int[] numbers, int target) {
        int[] index=new int[2];
        if(numbers == null||numbers.length<2)
            return index;       
        Arrays.sort(numbers);   
        int left=0;
        int right=numbers.length-1;
        while(left<right)
            {
            if(numbers[left]+numbers[right] == target)
                {
                index[0]=numbers[left];
                index[1]=numbers[right];
                break;
            }
            else if(numbers[left]+numbers[right] < target)
                {
                left++;
            }else
                {
                right--;
            }
        }
        return index;
    }


题目二:3 sum   数组中是否存在三个数a,b,c使得a+b+c = 0?

并且需要满足的条件为:

  • 1. triplet (a,b,c) 不能降序排列. (ie,a ≤ b ≤ c),   
  • 2. ArrayList<ArrayList<Integer>>中不能存放重复的triplet.

For example, given array S = {-1 0 1 2 -1 -4},

    A solution set is:
    (-1, 0, 1)
    (-1, -1, 2)
题解:从所需满足的条件判断,应该先对数组num排序,然后将3 Sum分解为【1 sum+2 sum】,即固定一个数字,另外的两个数组按照2 sum的解法,并且所要储存的是值,所2 sum可以采用两个下标的方法。

public class Solution {
    public ArrayList<ArrayList<Integer>> threeSum(int[] num) {
        ArrayList<ArrayList<Integer>> array=new ArrayList();
        if(num == null||num.length<3)
            return array;
        
        ArrayList<Integer> list=new ArrayList();

        Arrays.sort(num);//排序;
        for(int i=0;i<num.length-2;i++)
            {
            if(i>0&&num[i] == num[i-1])//不能有重复的triplet;
                continue;
           int left=i+1;
            int right=num.length-1;
            while(left<right)//防止越界;
                {
            int sum=num[i]+num[left]+num[right];
            if(sum == 0)
                {
                list.add(num[i]);
                list.add(num[left]);
                list.add(num[right]);
                array.add(list);
                list=new ArrayList();
                //left和right都要移位。
                left++;
                while(left<right&&num[left] == num[left-1])//防止有连续重复的值;
                    {
                    left++;
                }
                right--;
                while(right>left&&num[right] == num[right+1])//防止有连续重复的值;
                    {
                    right--;
                }
            }
            else if(sum<0)
                left++;
                else
                right--;
            }
        }
        return array;
    }

题目三:3 sum closed


错误分析:

closed为数组中三数之和中最接近target的,那么初始化closed时随便找三个数组元素求和就好了,如closed =num[0]+num[]1+num[2] is correct!

import java.util.*;
public class Solution {
    public int threeSumClosest(int[] num, int target) {
        if(num == null||num.length<3)
            return 0;
        
        Arrays.sort(num);
        int closed=Integer.MAX_VALUE;//closed =num[0]+num[]1+num[2] is correct!  
       // System.out.println(Math.abs(Integer.MAX_VALUE-(-1)));得:-2147483648。补码的原因。
        for(int i=0;i<num.length-2;i++)
            {
            if(i>0&&num[i] == num[i-1])
                continue;
            
            int left=i+1;
            int right=num.length-1;
            while(left<right)
                {
                int sum=num[i]+num[left]+num[right];
                if(sum == target)
                    {
                   return target;
                }
                if(Math.abs(target-sum)<Math.abs(closed-target))
                      {
                      closed=sum;
                   }
                
                if(sum<target)
                    {
                    left++; 
                }else
                    {
                     right--;
                }
            }
        }
        return closed;
    }
}


题目四:4 Sum

题目描述

一个有n个整数的数组,是否存在四个元素a, b, c, d使得 a + b + c + d = target? 找出所有的满足条件的四个为一组的元素。

 注:

  • 1.quadruplet (a,b,c,d) 不能降序排列. (ie, a ≤ b ≤ c ≤ d), 
  • 2. ArrayList<ArrayList<Integer>>中不能存放重复的quadruplet.
例如:

   given array S = {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)
 
 
题解:
1.先对数组进行排序;
2.固定一个数num[i],对之后的数进行3 Sum;
总的时间复杂度为O(N^3)!
public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
        ArrayList<ArrayList<Integer>> array=new ArrayList();
        if(num == null||num.length<4)
            return array; 
        ArrayList<Integer> list=new ArrayList();
        Arrays.sort(num);
        for(int i=0;i<num.length-3;i++)
            {
            if(i>0&&num[i] == num[i-1])
                continue;//避免重复;
            //3 Sum
            for(int j=i+1;j<num.length-2;j++)
                {
                if(j>i+1&&num[j] == num [j-1])
                    continue;//避免重复;
                int left=j+1;
                int right=num.length-1;
                while(left<right)
                    {
                    int sum=num[i]+num[j]+num[left]+num[right];
                    if(sum == target)
                        {
                         list.add(num[i]);
                         list.add(num[j]);
                         list.add(num[left]);
                         list.add(num[right]);
                        array.add(list);
                        list=new ArrayList();
                 //sum == target情况时,left++和right--操作不能遗漏,且两个都有必要!
                    left++;
                    while(left<right&&num[left] == num[left-1])//避免重复;
                        left++;
                    right--;
                    while(left<right&&num[right] == num[right+1])//避免重复;
                        right--;
                    }
                    else if(sum<target)
                        {
                        left++;
                    }else
                        {
                        right--;
                    }
                }
            }
        }
        return array;
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值