网站首页 > 教程文章 正文
两数之和
2次for循环O( N2 ) 的做法就不说了,大家都会。我说下O(N)时间复杂度的做法。
解题思路:
- 一次for循环。遍历的时候用字典记录下遍历到的值,不过是以num为key,以下标index为value
- 继续遍历的时候,就用 target - num作为key去字典中取值,如果取到了说明存在,返回结果
- 若没有取到,就以num为key,index为value存入字典
代码如下:
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var map = [Int: Int]()
for (i,num) in nums.enumerated() {
if let index = map[target - num] {
return [index, i]
}
map[num] = i
}
return []
}
三数之和:
其实这个题目有点难,暴力解法就是3层for循环,不过O( N3 )提交是肯定过不了的,这个题目还有一个要求就是不能重复。
解题思路:
先进行一次排序。因为这个题目考查的不是排序,所以我们可以直接使用系统自带的排序算法。
上图中,l的下标一开始是 i+1; r一开始就只想最后一个元素,下标为nums.count-1;
就以-4开始举一个例子来表述这个算法的解题思路:
- 开始时,i = 0, nums[i] = -4, l = i + 1, r = nums.count - 1
- 此时,nums[i] + nums[l] + nums[r] = -4-1+2 = -3,因为数组是排好序的,说明nums[l]太小了,所以l++;
- 直到l == 4,此时,nums[i] + nums[l] + nums[r] = -4+1+2 = -1还是不等于0,所以i++
- 此时i == 1,l = i+1 = 2,r = nums.count - 1,此时nums[i] + nums[l] + nums[r] = -1-1+2 = 0,所以将这组数据存入到结果数组中。然后l++.r--,进行下一次遍历。
代码如下:
class Solution {
func threeSum(_ nums: [Int]) -> [[Int]] {
if nums.count < 3 { return [] }
// 系统方法进行排序
let sortedNums = nums.sorted()
var result = [[Int]]()
let lastR = sortedNums.count - 1
for i in 0...(sortedNums.count - 3) {
// 去重1
if i > 0 && sortedNums[i] == sortedNums[i-1] { continue }
var l = i + 1; var r = lastR; let remain = 0 - sortedNums[i];
while (l < r) {
let sumLR = sortedNums[l] + sortedNums[r]
if sumLR == remain {
result.append( [sortedNums[i], sortedNums[l], sortedNums[r] ])
// 去重2
while (l < r && sortedNums[l] == sortedNums[l+1]) { l += 1 }
while (l < r && sortedNums[r] == sortedNums[r-1]) { r -= 1 }
l += 1
r -= 1
} else if sumLR < remain {
l += 1
} else {
r -= 1
}
}
}
return result
}
}
核心是如何去重的问题。举例子来说明重复的问题,代码里面有2处重复,我标记了分别为1和2。
先看第1处去重情况:看下图红色方框选中的两个-1。因为前面一个-1已经完成一次遍历。所以再碰到同样的 -1 就直接跳过。
再看第2处去重情况:如下图所示,当i = 0, l = 2, r = 6时,nums[i] + nums[l] + nums[r] = 0,所以马上l++, r--红色的表示转换后的样子,发现l++ 和 l指的指向是一样的,所以就跳过。r 和 r--指的指向是一样的,也跳过。这样就达到去重的目的。
总结:
今天主要分享了2道常考的算法题。2数之和和3数之和。2数之和的思路就是用字典来存储,用空间换时间的方式使时间复杂度为O(N)。3数之和就比较有难度了,核心就是如何去重的问题,我也在文中举例子来表达了是如何去重的。希望能帮助到大家。
- 上一篇: javascript中的模块系统_js模块类型
- 下一篇: 仓颉编程学习-变量_仓颉 编程语言
猜你喜欢
- 2025-09-03 一文带你彻底搞懂Proxy和Reflect!
- 2025-09-03 前端最新面试题及答案 (2025)_2021前端面试大全
- 2025-09-03 bind、call、apply 区别?如何实现一个bind?
- 2025-09-03 黑马程序员前端视频-黑马前端教程
- 2025-09-03 Rust从入门到放弃(一):数据类型_rust csdn
- 2025-09-03 仓颉编程学习-变量_仓颉 编程语言
- 2025-09-03 javascript中的模块系统_js模块类型
- 2025-09-03 我以为自己懂闭包,直到遇见了它的真面目
- 2025-09-03 JavaScript面试题精选:10个高频问题详解
- 2025-09-03 第15天|16天搞定前端,javascript语法篇(干货)
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- mybatis plus page (35)
- vue @scroll (38)
- 堆栈区别 (33)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)
- redis aof rdb 区别 (33)
- 302跳转 (33)
- http method (35)
- js array splice (33)