zoukankan      html  css  js  c++  java
  • 三数之和

    给你一个包含 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

    注:题目来源于力扣

    超暴力解题思路

    三数之和,可以看作是固定一个值,求解剩下两个数----双指针。先对数组进行排序(双指针),当符合条件的时候,组装数组,并判断是否出现重复值。如果不重复则加入结果中。

    代码

    func threeSum(nums []int) [][]int {
    
    	if len(nums)<=2{
    		return nil
    	}
    	result := make([][]int,0)
    	sort.Ints(nums)
    	for i:=0;i<len(nums);i++{
    		tmp := 0-nums[i]
    		log.Println(tmp)
    		x := 0
    		y := len(nums)-1
    		for x<y {
    			if x == i{
    				x++
    				continue
    			}
    			if y==i {
    				y--
    				continue
    			}
    			if nums[x]+nums[y] < tmp {
    				x++
    			}else if nums[x] + nums[y] > tmp {
    				y--
    			}else if nums[x] + nums[y] == tmp {
    				tmpArr := []int{nums[i],nums[x],nums[y]}
    				sort.Ints(tmpArr)
    				if !dupRemove(result,tmpArr) {
    					result =  append(result,tmpArr)
    				}
    				x++
    				y--
    			}
    
    		}
    	}
    	return result
    }
    
    // 查重
    func dupRemove(result [][]int,tmp []int)bool{
    	for i:=0;i<len(result);i++{
    		count := 0
    		for j:=0;j<len(result[i]);j++{
    			if result[i][j] == tmp[j] {
    				count++
    			}
    			if count == len(tmp) {
    				return true
    			}
    		}
    	}
    	return false
    }
    

    正确解法

    上面的解法是对的,但是输在了去重这部分。最后一根稻草竟然是去重。哈,安排(双指针遍历之前的操作)。

    • 对数组进行排序。双指针需得对数组进行排序,然后对数组进行排序能够避免回头查找,实现线性查找
    • 遍历排序后的数组
      • 如果nums[i] > 0,立即跳出循环。因为数组是按照从小到大排序的,如果nums[i]>0,则后面就没有负数,使得nums[i] + nums[i+1]+nums[i+2] = 0
      • 对于重复的元素,跳过。假设数组中的三个数为:a,b,c。又因为a<=b<=c,则我们只要对a和b遍历去重就可以避免找到结果集之后还需要查重。a的遍历从1开始就考虑是否重复,b的遍历要从i+1(假设a的下表为i)就要考虑是否重复了。b不能从0开始重复,因为会出现:-1 -1 0 1 2中不能找出-1 -1 2。

    代码

    func threeSum(nums []int) [][]int {
    
    	if len(nums)<=2{
    		return nil
    	}
    	result := make([][]int,0)
    	sort.Ints(nums)
    	for i:=0;i<len(nums);i++{
    		if nums[i] > 0 {
    			return result
    		}
    		if i>0 && nums[i] == nums[i-1] {
    			continue
    		}
    		tmp := 0-nums[i]
    		x := i + 1
    		y := len(nums)-1
    		for x<y {
    			// 如果这里的x只是大于零的话,可能就会出现一种情况就是查到了a的枚举 -1 -1 0 1 2 就会吞掉:-1 -1 2的情况
    			if x>i+1 && nums[x] == nums[x-1] {
    				x++
    				continue
    			}
    			if y>=0 && y<len(nums)-1 && nums[y] == nums[y+1] {
    				y--
    				continue
    			}
    			if nums[x]+nums[y] < tmp {
    				x++
    			}else if nums[x] + nums[y] > tmp {
    				y--
    			}else if nums[x] + nums[y] == tmp {
    				tmpArr := []int{nums[i],nums[x],nums[y]}
    				result =  append(result,tmpArr)
    				x++
    				y--
    			}
    		}
    	}
    	return result
    }
    
    
  • 相关阅读:
    分部视图在ASP.NET MVC中的应用
    SVN、Git设置提交时忽略的文件
    TortoiseSVN使用步骤和trunk,Branch,Tag详细说明
    SQL Server系统表介绍与使用
    C#中Task的使用简单总结
    Auto Encoder用于异常检测
    mac bash 下使用vi 快捷方式——因为没有alt键 所以没有办法 用vi模式也非常方便的
    daal utils printNumericTable
    https 不会被中间人攻击——因为中间人即使拿到了数据,也是加密的
    Let's Encrypt 免费通配符 SSL 证书申请教程——但是也需要email,域名所有权等,如果是黑产用的话会这样用吗?会不会暴露自己身份???
  • 原文地址:https://www.cnblogs.com/MyUniverse/p/14866367.html
Copyright © 2011-2022 走看看