经典京东面试原题

写在前面

今天在「京东」题库中翻到一道经典题。

众所周知,题目越经典,评论区越逆天。

说归说,闹归闹,这道题还是要掌握的。

毕竟除了京东,汇量科技也在测试开发中考过:

下面一起来看看吧 ~

题目描述

平台:LeetCode

题号:16

给定一个包括 <math xmlns="http://www.w3.org/1998/Math/MathML"> n n </math>n 个整数的数组 nums 和 一个目标值 target

找出 nums 中的三个整数,使得它们的和与 target 最接近。

返回这三个数的和。

每组输入只存在唯一答案。

示例:

ini 复制代码
输入:nums = [-1,2,1,-4], target = 1

输出:2

解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

提示:

  • <math xmlns="http://www.w3.org/1998/Math/MathML"> 3 < = n u m s . l e n g t h < = 1 0 3 3 <= nums.length <= 10^3 </math>3<=nums.length<=103
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> − 1 0 3 < = n u m s [ i ] < = 1 0 3 -10^3 <= nums[i] <= 10^3 </math>−103 <=nums[i] <=103
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> − 1 0 4 < = t a r g e t < = 1 0 4 -10^4 <= target <= 10^4 </math>−104 <=target <=104

排序 + 双指针

对数组进行排序,使用三个指针 ijk 分别代表要找的三个数。

  1. 通过枚举 i 确定第一个数,另外两个指针 jk 分别从左边 i + 1 和右边 n - 1 往中间移动,找到满足 nums[i] + nums[j] + nums[k] 最接近 target 的唯一解。

  2. jk 指针的移动逻辑,分情况讨论 sum = nums[i] + nums[j] + nums[k]

    • sum > targetk 左移,使 sum 变小
    • sum < targetj 右移,使 sum 变大
    • sum = target:找到最符合要求的答案,直接返回

为了更快找到答案,对于相同的 i,可以直接跳过下标。

Java 代码:

Java 复制代码
class Solution {
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int n = nums.length, ans = nums[0] + nums[1] + nums[2];
        for (int i = 0; i < n; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            int j = i + 1, k = n - 1;
            while (j < k) {
                int sum = nums[i] + nums[j] + nums[k];
                if (Math.abs(sum - target) < Math.abs(ans - target)) ans = sum;
                if (ans == target) {
                    return target;
                } else if (sum > target) {
                    k--;
                } else if (sum < target) {
                    j++;
                }
            }
        }
        return ans;
    }
}

C++ 代码:

C++ 复制代码
class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        int n = nums.size(), ans = nums[0] + nums[1] + nums[2];
        for (int i = 0; i < n; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            int j = i + 1, k = n - 1;
            while (j < k) {
                int sum = nums[i] + nums[j] + nums[k];
                if (abs(sum - target) < abs(ans - target)) ans = sum;
                if (ans == target) {
                    return target;
                } else if (sum > target) {
                    k--;
                } else if (sum < target) {
                    j++;
                }
            }
        }
        return ans;
    }
};

Python 代码:

Python 复制代码
class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        n, ans = len(nums), nums[0] + nums[1] + nums[2]
        for i in range(n):
            if i > 0 and nums[i] == nums[i - 1]: 
                continue
            j, k = i + 1, n - 1
            while j < k:
                s = nums[i] + nums[j] + nums[k]
                if abs(s - target) < abs(ans - target):
                    ans = s
                if ans == target:
                    return target
                elif s > target:
                    k -= 1
                elif s < target:
                    j += 1
        return ans

TypeScript 代码:

TypeScript 复制代码
function threeSumClosest(nums: number[], target: number): number {
    nums.sort((a, b) => a - b);
    let n = nums.length, ans = nums[0] + nums[1] + nums[2];
    for (let i = 0; i < n; i++) {
        if (i > 0 && nums[i] == nums[i - 1]) continue;
        let j = i + 1, k = n - 1;
        while (j < k) {
            const sum = nums[i] + nums[j] + nums[k];
            if (Math.abs(sum - target) < Math.abs(ans - target)) ans = sum;
            if (ans == target) {
                return target;
            } else if (sum > target) {
                k--;
            } else if (sum < target) {
                j++;
            }
        }
    }
    return ans;
};
  • 时间复杂度:排序的复杂度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( log ⁡ n ) O(\log{n}) </math>O(logn),对于每个 i 而言,最坏的情况 jk 都要扫描一遍数组的剩余部分,复杂度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2)。整体复杂度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2)
  • 空间复杂度: <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n ^ 2) </math>O(n2)

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

相关推荐
梦想CAD控件6 分钟前
在线CAD开发包结构与功能说明
前端·javascript·vue.js
张拭心10 分钟前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
时光不负努力11 分钟前
typescript常用的dom 元素类型
前端·typescript
小怪点点16 分钟前
大文件切片上传
前端
子玖17 分钟前
go实现通过ip解析城市
后端·go
时光不负努力17 分钟前
TS 常用工具类型
前端·javascript·typescript
SuperEugene18 分钟前
Vue状态管理扫盲篇:Vuex 到 Pinia | 为什么大家都在迁移?核心用法对比
前端·vue.js·面试
张拭心21 分钟前
Android 17 来了!新特性介绍与适配建议
android·前端
Java不加班24 分钟前
Java 后端定时任务实现方案与工程化指南
后端
徐小夕25 分钟前
pxcharts-vue:一款专为 Vue3 打造的开源多维表格解决方案
前端·vue.js·github