Python习题——2018-04-25作业

3Sum Closest

题目链接:LeetCode #16

题目描述

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).

思路

暴力解法是,任取列表中的三个数相加,计算其与目标值的距离(即相减再取绝对值),如果距离为0就直接返回目标值。如果距离不为0,将距离与当前最短距离(初始化为列表前三个数之和)比较,如果距离小于当前最短距离,则取代之,然后取另外三个数,重复以上步骤。最坏情况是遍历列表中任意三个数的组合,时间复杂度为 O ( n 3 )

考虑用“从两边向中间靠拢”的方法来优化遍历的过程。这种方法需要列表是有序的,所以先对列表进行排序。另外,从两边向中间靠拢涉及的是两个下标的变化过程,所以应该每次先固定一个数,变化其余两个数。

具体做法如下:

  1. 对列表进行排序。
  2. 取三个下标i、j和k(i < j < k)。令i = 0。
  3. 令j = i + 1,k = len(nums) - 1。
  4. 将这三个下标对应的数相加,计算其与目标值的距离(即相减再取绝对值),如果距离为0就直接返回目标值,算法结束。如果距离不为0,将距离与当前最短距离(初始化为列表前三个数之和)比较,如果距离小于当前最短距离,则取代之。 然后考虑对j和k采用“从两边向中间靠拢”,即如果当前三个数的和小于目标值,则让j自增,否则让k自减。重复此步骤,直到j不小于k。
  5. 如果i对应的数是列表中从右往左第三个元素,则返回当前最短距离,算法结束。否则让i自增,回到步骤3。

由于使用了“从两边向中间靠拢”,则实际上靠拢的过程是线性的复杂度,即 O ( n ) 。再考虑外层i的循环,那么这个算法的时间复杂度应为 O ( n 2 )

代码

class Solution:
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        nums.sort()
        size = len(nums)
        tmp = sum(nums[0:3])
        for i in range(size - 2):
            j, k = i + 1, size - 1
            while j < k:
                now = nums[i] + nums[j] + nums[k]
                if now == target:
                    return target
                if now < target:
                    j += 1
                else:
                    k -= 1
                if abs(tmp - target) > abs(now - target):
                    tmp = now
        return tmp

猜你喜欢

转载自blog.csdn.net/Draymond_666/article/details/80087456