数组练习题:两数之和三数之和四数之和

Posted 一朵花花

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数组练习题:两数之和三数之和四数之和相关的知识,希望对你有一定的参考价值。

两数之和

题目:


暴力求解: 直接遍历数组,依次求和进行比较即可

代码实现:

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

三数之和

题目:


思考分析:

排序 + 双指针:

  1. 先对数组进行排序 Arrays.sort
  2. 使用指针 i 遍历数组,再用 left 和 right分别指向 i+1 和 length-1
  3. 遍历时,当 nums[ i ] > 0时,跳出循环,最小的首元素>0,则不可能出现三数之和为0
  4. 去重:出现以下情况,均跳过该元素,否则可能出现重复组合
    a) i > 0 且 nums[ i ] = nums[ i-1] 时
    b) left < right 且 nums[ left ] = nums[ left -1 ]时
    c) left < right 且 nums[ right ] = nums[ right + 1 ]时

画图理解:

代码实现:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        if(nums == null){
            return null;
        }
        List<List<Integer>> array = new ArrayList<List<Integer>>();
        //先对数组进行排序
        Arrays.sort(nums);
        for(int i = 0;i < nums.length - 2;i++){
            if(nums[i] > 0){
                break;
            }
            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }
            int left = i+1;
            int right = nums.length-1;
            while(left < right){
                if(nums[i]+nums[left]+nums[right]==0){
                    array.add(Arrays.asList(nums[i],nums[left],nums[right]));
                    left++;
                    right--;
                    while(left < right && nums[left] == nums[left-1]){
                        left++;
                    }
                    while(left < right && nums[right] == nums[right+1]){
                        right--;
                    }
                }
                else if(nums[i]+nums[left]+nums[right] > 0){
                    right--;
                }
                else{
                    left++;
                }

            }
        }
        return array;
    }
}

四数之和

题目:


思考分析:
和三数之和类似,只不过多了一层循环,且比较的对象变成了 target,这里不过多分析了,直接上代码

代码实现:

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> array = new ArrayList<List<Integer>>();
        //数组排序
        Arrays.sort(nums);
        int n = nums.length;
        for(int i = 0;i < n-3;i++){
            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }
            if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target){
                break;
            }
            if(nums[i] + nums[n-3] + nums[n-2] + nums[n-1] < target){
                continue;
            }
            for(int k = i + 1;k < n-2;k++){
                if(k > i+1 && nums[k] == nums[k-1]){
                    continue;
                }
                if(nums[i] + nums[k] + nums[k+1] + nums[k+2] > target){
                    break;
                }
                if(nums[k] + nums[i] + nums[n-2] + nums[n-1] < target){
                    continue;
                }
                int left = k + 1;
                int right = n - 1;
                while(left < right){
                    int sum = nums[i] + nums[k] + nums[left] + nums[right];
                    if(sum == target){
                        array.add(Arrays.asList(nums[i],nums[k],nums[left],nums[right]));
                        while(left < right && nums[left] == nums[left+1]){
                            left++;
                        }
                        left++;
                        while(left < right && nums[right] == nums[right-1]){
                            right--;
                        }
                        right--;
                    }
                    else if(sum > target){
                        right--;
                    }
                    else{
                        left++;
                    }

                }
            }
        }
        return array;
    }
}

最接近的三数之和

题目:

思考分析:

  • 先对数组进行排序
  • 使用 i 遍历数组
  • 定义 left,right 分别指向 第二个元素和尾元素下标
  • 依次求和 sum,sum 与 target 做差,比较大小
  • 定义一个 ret,存放一个很大的数,每次做差后,将 ret 和 (sum 和 target 差) 的最小值赋值给 ret
  • 最终返回 ret

代码实现:

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

补充

(1).Math.abs

Math.abs(x)=|x|,x是什么类型,返回的便是什么类型
例:Math.abs( ),若括号里为 int 类型,则返回值是 int 类型的绝对值

(2).Arrays.asList

该方法是将数组转化成List集合的方法,返回由指定数组支持的固定大小的列表

详情可参考:在线文档

以上是关于数组练习题:两数之和三数之和四数之和的主要内容,如果未能解决你的问题,请参考以下文章

力扣16-最接近的三数之和&力扣18-四数之和

18. 四数之和

leetcode 18. 四数之和

1.两数之和

15. 三数之和

LeetCode刷题系列之-多数之和类型