1. 程式人生 > >演算法34--3Sum,3Sum Closest,4Sum

演算法34--3Sum,3Sum Closest,4Sum

Given an array nums of n integers, are there elements abc in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

給定一個數組,選出三元組使其和為0  三元組不能重複。

將陣列排序,固定第一個指標k來進行遍歷,然後利用雙指標i,j分別從陣列k+1--len-1向中點尋找,

當sum=nums[k]+nums[i]+nums[j]==0  直接輸出

當sum<0,說明過小,此時移動i指標即可,i++,否則移動j即可,j--

def threeSum(nums=[-2,0,0,2,2]):
        nums.sort()
        #print(nums)
        rr = []
        for k in range(len(nums)-1):
            i = k+1                        
            j = len(nums)-1        
            while i<j:
                #print(k, i, j)                
                sum = nums[k] + nums[i] + nums[j]
                if sum==0:
                    rr.append([nums[k], nums[i], nums[j]])                                           
                    i += 1
                    j -= 1
                elif sum<0:
                    i += 1
                else:
                    j -= 1
        return rr

程式碼如上所示,輸出結果並沒有去除重複結果,現在考慮一下重複值的產生情況:

給定陣列以及三個指標k,i,j     0---k---i----j---len-1

當nums[k-1]==nums[k]相同時,可以直接k++,進行下一次迴圈,否則可能會產生重複  例如  -1   -1  0  1  1當k=0與k=1時會產生重複;

當k遍歷依次遞加沒有重複,考慮i位置的重複,當某一元組(k,i,j)符合條件時,此時如果nums[i+1]==nums[j],此時如果執行i++,j--,可能會產生重複,處理方式是當找到符合條件的三元組時,此時應該移動i,j的指標直到nums[i·]不等於nums[i],以及nums[j`]不等於nums[j]

def threeSum(nums=[-2,0,0,2,2]):
        nums.sort()
        #print(nums)
        rr = []
        for k in range(len(nums)-1):
            if k>=1 and nums[k-1]==nums[k]:
                continue
            i = k+1                        
            j = len(nums)-1        
            while i<j:
                #print(k, i, j)                
                sum = nums[k] + nums[i] + nums[j]
                if sum==0:
                    rr.append([nums[k], nums[i], nums[j]])                        
                    while i<j and nums[i+1]==nums[i]:                        
                        i += 1
                    while i<j and nums[j-1]==nums[i]:
                        j -= 1
                    i += 1
                    j -= 1
                elif sum<0:
                    i += 1
                else:
                    j -= 1
        return rr

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

給定陣列,找到一個三元組,使其和最接近target.

將陣列排序,維持一個全域性最小差值,利用陣列有序以及三指標來調整位置,尋找可能的最小差值

def threeSumClosest(nums=[-4,-1,1,2], target=1):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        nums.sort()
        minv = nums[0]+nums[1]+nums[-1]
        mind = abs(nums[0]+nums[1]+nums[-1]-target)
        #print(minv, mind)
        for k in range(len(nums)):
            i = k+1
            j = len(nums)-1
            while i<j:
                diff = nums[k] + nums[i] + nums[j] - target
                #print(k,i,j,diff,mind)
                if diff==0:
                    return target
                else:
                    if abs(diff)<=mind:
                        minv = nums[k] + nums[i] + nums[j]
                        mind = abs(diff)
                        #print(minv, mind)
                    if diff<0:
                        i += 1
                    else: 
                        j -= 1
        return minv

Given an array nums of n integers and an integer target, are there elements abc, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

The solution set must not contain duplicate quadruplets.

Example:

Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

給定一個數組,尋找非重複四元組使其和等於target.

類似於三元組和問題,如果暴力求解時間複雜度為N4.

首先將陣列排序,陣列變為有序之後。利用兩個指標來遍歷前兩個元素,後面再利用雙指標從頭尾向中間遞進,依次尋找符合條件的組合解,將時間複雜度降為N2logN

class Solution:
    def fourSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[List[int]]
        """
        nums.sort()
        rr = []
        for k in range(len(nums)):
            if k>0 and nums[k]==nums[k-1]:
                continue
            for m in range(k+1, len(nums)):
                if m>k+1 and nums[m]==nums[m-1]:
                    continue
                i=m+1
                j=len(nums)-1
                while i<j:
                    sum=nums[k]+nums[m]+nums[i]+nums[j]
                    if sum==target:
                        rr.append([nums[k],nums[m],nums[i],nums[j]])
                        while i<j and nums[i]==nums[i+1]:
                            i += 1
                        while i<j and nums[j]==nums[j-1]:
                            j -= 1
                        i += 1
                        j -= 1
                    elif sum<target:
                        i += 1
                    else:
                        j -= 1
        return rr     

去重要考慮四個指標的去重,k,m分別從頭向尾遍歷,因此去重要考慮每一個元素與前一個元素是否相同,如果相同則直接跳過進行下一個元素遍歷;i,j分別從頭尾向中間遍歷遞進,當找到符合條件的元組時,i,j應該繼續向中間逼近,直到取到新的不同於上一個值為止,繼續進行求和與target的大小判斷,即可去重。