• 0015leetcode算法实现之三数之和3sumpython&golang实现 Marathon


    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

    注意:答案中不可以包含重复的三元组。

    示例 1:

    输入:nums = [-1,0,1,2,-1,-4]
    输出:[[-1,-1,2],[-1,0,1]]
    示例 2:

    输入:nums = []
    输出:[]
    示例 3:

    输入:nums = [0]
    输出:[]

    提示:

    0 <= nums.length <= 3000
    -105 <= nums[i] <= 105

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/3sum

    python

    # 三数之和为0
    
    class Solution:
        def threeSum(self, nums: [int]) -> [int]:
            """
            先排序,再用双指针,排序O(nlogn),寻找二三个数O(n),寻找一二三个数O(n^2),所以时间O(n),空间O(logn)
            思路:整形数组,先排序,利于后面寻找三个数,每轮搜索,固定第一个数,第二个数右移,第三个数左移,比较和与target
            算法流程:
            1.排序数组,初始化返回数组ans []
            2.遍历数组,检查当前的first指向元素是否大于0,成立则break,不可能有a+b+c=0成立,检查first是大于0即第二个数的first开始, 且与前一个元素值相同,继续下一个first
            3.每次遍历寻找第一个数时,初始化third为最后一个元素,第一个元素值的相反数即为搜索本次二三个数和的目标值target
            4.再次遍历数组,从first+1开始,检查second和second-1对应元素值是否相等,等则continue,继续寻找second
            5.当second<third且和大于target时,由于排序,此时只有减小和才可能等于target,即third--, 重复移动third寻找合适的third,当second=third或和<=target时,break当前的while循环
            6.上步break, 检查second==third, 成立则break second third,应该更新first,继续2 3 4 5 6
            7.5步的while循环仅second=third或和等于小于target时break, 如果和等target则将此三个数append进ans, 如果不等target,其实就是和小于target, 即继续更新second, 重复4 5 6 7步
            8.重复2-7,直到break或遍历完数组,返回ans
            :param nums:
            :return:
            """
            nums.sort() # 为便于后面寻找,先排序
            n = len(nums)
            ans = [] # 初始化返回数组
            for first in range(n):
                if nums[first] > 0: # 由于数组已经排序,只要第一个数大于0,后面的数肯定都大于0,不可能出现a+b+c=0,直接break,就不用再去寻找后面的可能性
                    break
                if first > 0 and nums[first] == nums[first-1]: # 第一个数在遍历到第二及以后的数时,检查是否与前一个数重复,是则continue,否则继续寻找二三个数
                    continue
                third = n -1 # 每次更新第一个数时,third指向最后一个数
                target = -nums[first] # target对第一个数取反,后面的二三个数,只需要考虑其和与target的比较,每次更新第一个数的时候,更新target
                for second in range(first+1, n):
                    # 第二个数与上次遍历相同,继续遍历,寻找第二个数
                    if second > first + 1 and nums[second] == nums[second-1]:
                        continue
                    # 左指针在右指针左侧,且和大于target
                    while second < third and nums[second] + nums[third] > target: # 由于是排序数组,大概率应该是其和小于target的,只有当左指针在右指针左边,且和大于target,左移右指针third--,更新third
                        third -= 1
                    # 左右指针重合或左右指针数和小于等于target
                    if second == third: # 大概率是和小于target,此时应该更新second,和才会变大,检查左右指针是否相等,如果等,即二三数为同一个数,必须break
                        break
                    if nums[second] + nums[third] == target: # 检查二三数和是否等于target, 成立则append进ans,继续更新second
                        ans.append([nums[first], nums[second], nums[third]])
            return ans
    
    
    
    
    if __name__ == "__main__":
        nums = [2,6,7,-8,3,4,2,-13,3,-5]
        nums1 = []
        nums2 = [0]
        nums3 = [1,2]
        test = Solution()
        print(test.threeSum(nums)) # [[-13, 6, 7], [-8, 2, 6], [-5, 2, 3]]
        print(test.threeSum(nums1)) # []
        print(test.threeSum(nums2)) # []
        print(test.threeSum(nums3)) # []
    

    golang

    package main
    
    import (
    	"fmt"
    	"sort"
    )
    
    func main() {
    	nums := []int{2, 6, 7, -8, 3, 4, 2, -13, 3, -5}
    	fmt.Println(threeSum(nums))
    }
    
    // 排序+双指针
    func threeSum(nums []int) [][]int {
    	sort.Ints(nums)
    	n := len(nums)
    	ans := [][]int{}
    	var first int
    
    	for first = 0; first < n; first++ {
    		if nums[first] > 0 {
    			break
    		}
    		if first > 0 && nums[first] == nums[first-1] {
    			continue
    		}
    		third := n - 1
    		target := -nums[first]
    		for second := first + 1; second < n-1; second++ {
    			if second > first+1 && nums[second] == nums[second-1] {
    				continue
    			}
    			for second < third && nums[second]+nums[third] > target {
    				third--
    			}
    			if second == third {
    				break
    			}
    			if nums[second]+nums[third] == target {
    				ans = append(ans, []int{nums[first], nums[second], nums[third]})
    			}
    		}
    	}
    	return ans
    }
    
  • 相关阅读:
    ajax的一些知识
    前端性能优化汇总
    jquery实现一些小动画二
    python简单日志处理
    逆波兰式---C实现
    java常见异常
    Hive与HBase集成及常见问题解决
    SQL for HBase
    Demystifying the Skip Scan in Phoenix
    Difference between DDL, DML and DCL commands
  • 原文地址:https://www.cnblogs.com/davis12/p/15473532.html
Copyright © 2020-2023  润新知