zoukankan      html  css  js  c++  java
  • LeetCode15.ThreeSum

    题目

    给你一个包含 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
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    解题思路

    1. 暴力破解

    三重循环,时间复杂度O(n^3)
    

    2. 双重循环 + map

    两重循环
    第三重循环直接去map中查找
    时间复杂度 O(n^2)
    

    3. 排序 + 双指针

    先将数组元素进行排序(便于跳过重复元素,如果当前元素和前一个元素相同则跳过)
    从第一个元素进行循环
    设置两个指针(左右指针向内收缩):
        左指针 = 循环元素后第一个元素
        右指针 = 数组最后一个元素
    如果循环元素 + 左指针元素 + 右指针元素:
        大于0:
            右指针向左移动一位(因为结果大于0,而数组已经是有序的,所以要减小大的值)
        小于0:
            左指针向右移动一位
        两指针相遇:
            结束,不存在
    优化:如果循环的元素大于0,则排序后的数组另外两个数肯定也大于0,sum不可能等于0,所以直接break    
    
    https://leetcode-cn.com/problems/3sum/solution/zhi-zhen-yi-dong-guo-cheng-zhong-tiao-guo-zhong-fu/
    

    代码

    // 排序 + 双指针
    func threeSum(nums []int) [][]int {
    // 对元素进行排序
    sort.Ints(nums)
    // 返回结果
    result := [][]int{}
    // 循环长度-2次,因为最后左右两个指针元素可以不用循环
    for i := 0;i < len(nums)-2;i++ {
    	n1 :=nums[i]
    	// 如果当前元素已经大于0,直接跳出循环
    	if n1 > 0{
    		break
    	}
    	// 如果与上一个元素相同跳过
    	if i > 0 && n1 == nums[i - 1] {
    		continue
    	}
    	// 左右两个指针
    	l,r := i+1,len(nums)-1
    	for l < r{
    		n2,n3 := nums[l],nums[r]
    		// 如果三数之和等于0,保存结果并跳过重复元素
    		if n1 + n2 + n3 == 0{
    			result = append(result,[]int{n1,n2,n3})
    			for l < r && nums[l] == n2{
    				l++
    			}
    			for l < r && nums[r] == n3{
    				r--
    			}
    			// 小于0说明元素太小了,左指针向大的元素方向移动
    		}else if n1 + n2 + n3 < 0{
    			l++
    		}else{
    			r--
    		}
    	}
    }
    return result
    }
    
    // map加速查询
    func threeSum2(nums []int) [][]int {
    	// 对数组进行排序
    	sort.Ints(nums)
    	// 存储nums元素数量
    	var dataCountMap = make(map[int]int)
    	// 将nums数组中的元素添加到map中
    	for _,v := range nums {
    		// 已经存在数量置为1,否则++
    		if _,ok:= dataCountMap[v];!ok{
    			dataCountMap[v] = 1
    		}else{
    			dataCountMap[v]++
    		}
    	}
    	// 用于存储结果,达到去重作用
    	var solutionMap = make(map[[2]int]struct{})
    	for i := 0;i < len(nums) - 2;i++{
    		for j := i+1;j < len(nums)-1;j++{
    			// a+b+c = 0 c = -a-b
    			expected := -nums[i] - nums[j]
    			// 判断map中是否存在符合的元素,且元素要大于等于j索引上的元素,因为开始已经将数组排序了
    			if num,ok := dataCountMap[expected];ok && expected >= nums[j]{
    				// 如果和i或j索引元素一样将num局部变量--,作用是判断是否有足够数量的元素可供使用,不能使用同一个重复元素
    				if expected == nums[i]{
    					num--
    				}
    				if expected == nums[j]{
    					num--
    				}
    				if num > 0 {
    					solutionMap[[2]int{nums[i],nums[j]}] = struct{}{}
    				}
    			}
    		}
    	}
    	var result = make([][]int,len(solutionMap))
    	i := 0
    	for k := range solutionMap{
    		result[i] = []int{k[0],k[1],-k[0]-k[1]}
    		i++
    	}
    	return result
    }
  • 相关阅读:
    Dubbo与Eureka
    对称加密与非对称加密
    [转] SpringBoot2.0集成WebSocket,实现后台向前端推送信息
    [转] Druid简介(Spring Boot + Mybatis + Druid数据源【自己定制】)
    [转] rsync+inotify实现文件实时同步
    [转] windows server 几大实时同步软件比较
    [转] Springboot 整合RabbitMq ,用心看完这一篇就够了
    [转] Windows环境下部署RabbitMQ
    [转] 分布式缓存 Redis 集群搭建
    [转] 吞吐量(TPS)、QPS、并发数、响应时间(RT)概念
  • 原文地址:https://www.cnblogs.com/hzpeng/p/15033147.html
Copyright © 2011-2022 走看看