LeetCode 16. 3Sum Closest (Java版; Medium)

博客介绍了LeetCode中第16题3Sum Closest的问题,通过Java实现,利用排序和双指针将时间复杂度从O(N^2)降低到O(N),寻找与目标值(target)最接近的三数之和。
摘要由CSDN通过智能技术生成

welcome to my blog

LeetCode Top Interview Questions 16. 3Sum Closest (Java版; Medium)

题目描述
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).
第一次做; 排序+双指针; 有序数组上的双指针可以将O(N^2)的循环嵌套遍历降低为O(N)的循环遍历
//先对数组排序, 然后使用双指针; 核心: 双指针在有序数组上移动次数是O(N), 进而将本是O(N^2)的遍历转换成了O(N)的双指针移动
class Solution {
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int min = Integer.MAX_VALUE;
        int res = 0;
        for(int i=0; i<=nums.length-3; i++){
            int cur = nums[i];
            //双指针, 首尾向中间移动;移动原则: sum>target时right--, sum<target时left++  这个思路挺常用的, 但是没有理解透彻
            int left = i+1, right = nums.length-1;
            while(left<right){
                int sum = cur + nums[left] + nums[right];
                //先判断是否需要更新res
                int gap = Math.abs(sum-target);
                //再调整双指针
                if(gap<min){
                    min = gap;
                    res = sum;
                }
                if(sum>target)
                    right--;
                else if(sum<target)
                    left++;
                else
                    return sum;
            }
        }
        //看清楚了, 返回的是三个数的和
        return res;
    }
}
第一次做; 暴力, 记录所有三个数的和, 再找出离target最近的一个组合; 细节: 接近程度是靠差的绝对值衡量的, 绝对值越小越接近
//记录所有三个数的和, 再找出离target最近的一个组合
class Solution {
    public int threeSumClosest(int[] nums, int target) {
        HashMap<Integer,int[]> map = new HashMap<>();
        int n = nums.length;
        for(int i=0; i<=n-3; i++){
            for(int j=i+1; j<=n-2; j++){
                for(int k=j+1; k<=n-1; k++){
                    int sum = nums[i] + nums[j] + nums[k];
                    map.put(sum, map.getOrDefault(sum, new int[] {nums[i], nums[j], nums[k]}));
                }
            }
        }
        //
        int final_key=0, min = Integer.MAX_VALUE;
        //遍历哈希表
        for(Map.Entry<Integer, int[]> e : map.entrySet()){
            int sum = e.getKey();
            int gap = Math.abs(sum-target);
            if(gap<min){
                min = gap;
                final_key = sum;
            }
        }
        return final_key;
    }
}
力扣优秀题解
标签:排序和双指针
本题目因为要计算三个数,如果靠暴力枚举的话时间复杂度会到 O(n^3)O,需要降低时间复杂度
首先进行数组排序,时间复杂度 O(nlogn)
在数组 nums 中,进行遍历,每遍历一个值利用其下标i,形成一个固定值 nums[i]
再使用前指针指向 start = i + 1 处,后指针指向 end = nums.length - 1 处,也就是结尾处
根据 sum = nums[i] + nums[start] + nums[end] 的结果,判断 sum 与目标 target 的距离,如果更近则更新结果 ans
同时判断 sum 与 target 的大小关系,因为数组有序,如果 sum > target 则 end--,如果 sum < target 则 start++,如果 sum == target 则说明距离为 0 直接返回结果
整个遍历过程,固定值为 n 次,双指针为 n 次,时间复杂度为 O(n^2)

总时间复杂度:O(nlogn) + O(n^2) = O(n^2)O(nlogn)+O(n^2)=O(n^2)
class Solution {
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int ans = nums[0] + nums[1] + nums[2];
        for(int i=0;i<nums.length;i++) {
            int start = i+1, end = nums.length - 1;
            while(start < end) {
                int sum = nums[start] + nums[end] + nums[i];
                if(Math.abs(target - sum) < Math.abs(target - ans))
                    ans = sum;
                if(sum > target)
                    end--;
                else if(sum < target)
                    start++;
                else
                    return ans;
            }
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值