数组和问题
主要是围绕数组中一些数做操作,以达到某个目标,如目标和等。
1.两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
暴力法:
显然,可以用两个for循环,复杂度为 O ( n 2 ) O(n^2) O(n2)
双指针
首先将问题转化为公式,即
x
+
y
=
t
a
r
g
e
t
x + y = target
x+y=target。其中,
x
,
y
x,y
x,y 是可变的,那么,当
x
x
x 的值减少的时候,
y
y
y 的值必须增加,反之亦然,这样才有可能得到
t
a
r
g
e
t
target
target。而通过遍历的方式选择增减,自然想到的就是让一个数组有序。这样,通过左移或者右移,就能控制增减。x = nums[left], y = nums[right]
, 若和大于
t
a
r
g
e
t
target
target则可排除当前的
y
y
y,因为当前结果已经是含
y
y
y的两数之和中最小的了。反之亦然,这样就能通过一次遍历得到下标[left, right]
。复杂度为
O
(
n
log
n
)
O(n\log n)
O(nlogn)(快排)+
O
(
n
)
=
O
(
n
log
n
)
O(n) = O(n\log n)
O(n)=O(nlogn)
再进阶
由于上述方法需要排序,时间复杂度不是
O
(
n
)
O(n)
O(n)。这种时候,应该学会对式子进行一定的转换,如逆向思维等。如
x
+
y
=
t
a
r
g
e
t
⟺
x
=
t
a
r
g
e
t
−
y
x + y = target \iff x = target - y
x+y=target⟺x=target−y,即给定一个
y
y
y,则符合条件的
x
x
x是固定的,只要存在则该对数字就满足条件。而看某个数是否存在,最便捷的就是使用Set()
数据结构,因为查找的复杂度为
O
(
1
)
O(1)
O(1)。但由于本题需要的答案是下标而不是数值,因此应该使用Map()
。遍历数组时,将当前数据看作
x
x
x,查看当前数据是否在Map()
中,若在则当前下标与Map()
中记录的下标组合就是答案;若不存在则将当前数据看作
y
y
y,将需要的
x
=
t
a
r
g
e
t
−
y
x = target - y
x=target−y 存入Map()
中。
15.三数之和
给你一个包含 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]
输出:[]
暴力法
三个for循环搞定,复杂度
O
(
n
3
)
O(n^3)
O(n3)。但由于本题要求不重复,因此要需要做去重。去重可以有两种方式,第一种是在循环的时候注意去重,这时候往往想到的就是排序;第二种是得到所有选择后进行去重,这也可以通过排序得到,即将得到的三元组排序后放入Set()
中。
排序+双指针
首先, a + b + c = 0 ⟺ b + c = 0 − a a+b+c=0 \iff b + c = 0 - a a+b+c=0⟺b+c=0−a,是不是和两数之和一样了?即 t a r g e t = 0 − a target = 0 - a target=0−a。那么,只需要枚举每一个 a a a, 求对应的 b , c b,c b,c 即可。因此复杂度为 O ( n log n ) O(n \log n) O(nlogn) + O ( n ) O(n) O(n)(枚举 a a a)* O ( n ) O(n) O(n)(双指针求 b , c b,c b,c) = O ( n 2 ) O(n^2) O(n2)
拓展
该类问题有引出一个编程思想,即逆向思维。很多题目正着做看似很复杂,但其实换个角度就发现很简单。
417. 太平洋大西洋水流问题
字节跳动2018校招算法方向(第一批)第1题
2021阿里编程2星第1题
2021阿里编程4星第5题
1591. 奇怪的打印机 II(推荐)主要是理解思想