【Leetcode-015】三数之和(Java && C++实现)

这篇博客介绍了一种使用Java解决三数之和问题的方法,通过数组排序、双指针及递归调用来找到数组中和为目标值的三个整数。首先对数组进行排序,然后遍历数组,对于每个元素,利用已有的两数之和API寻找剩余两个数。过程中避免了重复元素的出现,时间复杂度为O(n^2),空间复杂度为O(n)。该方法适用于解决类似题目,如两数之和及其扩展问题。
摘要由CSDN通过智能技术生成


1 数组排序+双指针+递归调用(Java实现)

/*
    方法:数组排序 + 双指针 + 递归调用
    难度:中等
    思路:从二数之和扩展到三数之和
          对排序后的数组进行遍历时(第1个数),第2个数和第3个数调用已有的二数之和API
          遍历过程需保证第1个数不能出现重复(第2、3个数已控制不会出现重复结果)
    时间复杂度:O(n * n)
           数组排序O(n logn)
           计算二数之和的双指针操作O(n) → 循环调用n次
           总时间复杂度:O(n logn + O(n) * n) = O(n * n)
    空间复杂度:O(n)
    类似题目:t001、t018
*/

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        return threeSumTarget(nums, 0);
    }

    //返回数组nums中和为target的三元组
    public List<List<Integer>> threeSumTarget(int[] nums, int target){
        //对数组进行排序
        Arrays.sort(nums);

        List<List<Integer>> res = new ArrayList<>();
        //for循环遍历数组
        for(int i = 0; i < nums.length; i++){
            //调用二元组的函数twoSumTarget → 计算目标值为target - nums[i]的二元组
            List<List<Integer>> temps = twoSumTarget(nums, i + 1,target - nums[i]);

            if(!temps.isEmpty()){
                for(List<Integer> temp : temps){
                    temp.add(nums[i]);
                    res.add(temp);
                }
                //跳过左侧遍历过程中的重复元素
                while(i < nums.length - 1 && nums[i] == nums[i+1]) i++;
            }
        }
        return res;
    }

    //返回数组nums中和为target的二元组(循环的起始位置为start)
    public List<List<Integer>> twoSumTarget(int[] nums, int start ,int target){
        //对数组进行排序
        Arrays.sort(nums);
        int low = start;    //第2个元素的起始索引位置start
        int high = nums.length - 1;

        List<List<Integer>> res = new ArrayList<>();
        //while循环遍历数组
        while(low < high){
            //记录当前的左值和右值
            int left = nums[low];
            int right = nums[high];
            int sum = left + right;
            if(sum < target){
                while(low < high && nums[low] == left) low++; //跳过左侧所有重复的元素
            }else if(sum > target){
                while(low < high && nums[high] == right) high--; //跳过右侧所有重复的元素
            }else if(sum == target){
                //向结果集res中添加符合条件的结果
                res.add(new ArrayList<Integer>(Arrays.asList(left, right)));
                while(low < high && nums[low] == left) low++; //跳过左侧所有重复的元素
                while(low < high && nums[high] == right) high--; //跳过右侧所有重复的元素
            }
        }
        return res;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值