📜  门| Gate IT 2005 |问题8(1)

📅  最后修改于: 2023-12-03 15:42:13.971000             🧑  作者: Mango

门| Gate IT 2005 |问题8

本题为Gate IT 2005的第8个问题,测试程序员的数据结构和算法知识。

题目描述

给定一个数组和一个整数x,从数组中找出三个数的和最接近x的那一组,并返回它们的和。

实现函数:

def closest_sum(arr: List[int], x: int) -> int:
    pass
输入
  • arr: 一个包含n个整数的数组(3 <= n <= 10^3),数组中的元素为整数(-10^3 <= arr[i] <= 10^3)。
  • x: 一个整数(-10^3 <= x <= 10^3)
输出

一个整数,代表三个数的和最接近x的那一组并返回它们的和。

示例

示例1

输入:

arr = [-1, 2, 1, -4]
x = 1

输出:

2

解释:

最接近x(1)的是-1+2+1=2

示例2

输入:

arr = [-1, 2, 1, -4]
x = 3

输出:

2

解释:

最接近x(3)的是-1+2+1=2

示例3

输入:

arr = [1, 1, 1, 0]
x = -100

输出:

2

解释:

最接近x(-100)的是1+1+1=3,但是由于题目要求返回它们的和,因此答案为1+1=2

解题思路

本题需要找到三个数的和最接近x的那一组,因此需要对数组进行遍历,取出三个数的组合,然后比较它们的和与x的大小关系,找到最接近的那一组。

具体思路如下:

  1. 对数组进行排序,以便于后续处理
  2. 初始化一个最小差值(min_diff)为无穷大(inf)
  3. 遍历数组,假设当前元素为arr[i]
  4. 对arr[i+1:]进行遍历,假设当前元素为arr[j]
  5. 初始化两个指针(p, q), 分别指向i+1和len(arr)-1
  6. 每次将arr[p]+arr[q]+arr[j]与x进行比较,如果它们的和小于x,则移动p指针,即左指针向右移动,以便减小和的值; 如果它们的和大于x,则移动q指针,即右指针向左移动,以便减小和的值; 如果它们的和等于x,则直接返回x。
  7. 更新min_diff的值,如果当前差值比min_diff小,则用当前差值代替min_diff
  8. 重复步骤4-7,直到j指向数组的最后一个元素。
  9. 重复步骤3-8,直到i指向数组的倒数第三个元素。
  10. 返回min_diff+x,即为最接近x的三个数的和。
代码实现
from typing import List

def closest_sum(arr: List[int], x: int) -> int:
    arr.sort()
    n, inf = len(arr), float('inf')
    min_diff, res = inf, 0
    
    # i从0到n-3,j从i+1到n-2,k从j+1到n-1
    for i in range(n-2):
        for j in range(i+1, n-1):
            p, q = j+1, n-1
            while p < q:
                sum_ = arr[i] + arr[j] + arr[p] + arr[q]
                diff = sum_ - x
                if abs(diff) < min_diff:
                    min_diff = abs(diff)
                    res = sum_
                if diff < 0:
                    p += 1
                elif diff > 0:
                    q -= 1
                else:
                    return x
    
    return res
复杂度分析
  • 时间复杂度:最坏情况下为O(n^3),因为需要三重循环遍历整个数组。
  • 空间复杂度:O(1),只使用了常量级别的辅助空间。
总结

本题考察了数组的排序、双指针等知识点,实现上比较简单,但需要一定的思考,特别是要考虑到所有情况,比如数组中可能有重复元素、可能存在多个解等。