LeetCode-Array-I
LeetCode - topics: Array (Part I)
1. Two Sum
Given an array of integers nums
and an integer target
, return indices of the two numbers such that they add up to target
.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Example 1:
1 | Input: nums = [2,7,11,15], target = 9 |
Example 2:
1 | Input: nums = [3,2,4], target = 6 |
Constraints:
2 <= nums.length <= 103
-109 <= nums[i] <= 109
-109 <= target <= 109
- Only one valid answer exists.
Solution:
1 | func twoSum(nums []int, target int) []int { |
Note:
牺牲空间换时间
2. Median of Two Sorted Arrays
Given an array of integers nums
and an integer target
, return indices of the two numbers such that they add up to target
.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Example 1:
1 | Input: nums = [2,7,11,15], target = 9 |
Example 2:
1 | Input: nums = [3,2,4], target = 6 |
Constraints:
2 <= nums.length <= 103
-109 <= nums[i] <= 109
-109 <= target <= 109
- Only one valid answer exists.
Solution:
1 | func findMedianSortedArrays(nums1 []int, nums2 []int) float64 { |
Note:
0004. Median of Two Sorted Arrays | LeetCode Cookbook
11. Container With Most Water
Given n
non-negative integers a1, a2, ..., an
, where each represents a point at coordinate (i, ai)
. n
vertical lines are drawn such that the two endpoints of the line i
is at (i, ai)
and (i, 0)
. Find two lines, which, together with the x-axis forms a container, such that the container contains the most water.
Notice that you may not slant the container.
Example 1:
1 | Input: height = [1,8,6,2,5,4,8,3,7] |
Example 2:
1 | Input: height = [1,1] |
Constraints:
n = height.length
2 <= n <= 3 * 104
0 <= height[i] <= 3 * 104
Solution:
1 | func maxArea(height []int) int { |
Note:
对撞指针,注意和连续面积的题目做区分。
15. 3Sum
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Notice that the solution set must not contain duplicate triplets.
Example 1:
1 | Input: nums = [-1,0,1,2,-1,-4] |
Example 2:
1 | Input: nums = [] |
Example 3:
1 | Input: nums = [0] |
Constraints:
0 <= nums.length <= 3000
-105 <= nums[i] <= 105
Solution:
1 | class Solution: |
Note:
先排序,方便移动左右’指针’,注意对排序后的数组进行剪枝;对结果重复项要注意
16. 3Sum Closest
Given an array nums
of n integers and an integer target
, find three integers in nums
such that the sum is closest to target
. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example 1:
1 | Input: nums = [-1,2,1,-4], target = 1 |
Constraints:
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4
Solution:
1 | class Solution: |
Note:
[3Sum](#15. 3Sum)的兄弟题,判断离target最近的一个组合,先排序,然后进行三数加和,通过加和结果与target的大小比较,移动指针(排序的意义)
18. 4Sum
Given an array nums
of n integers and an integer target
, are there elements a, b, c, and d in nums
such that a + b + c + d = target
? Find all unique quadruplets in the array which gives the sum of target
.
Notice that the solution set must not contain duplicate quadruplets.
Example 1:
1 | Input: nums = [1,0,-1,0,-2,2], target = 0 |
Example 2:
1 | Input: nums = [], target = 0 |
Constraints:
0 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
Solution:
1 | class Solution: |
Note:
[Two Sum](#1. Two Sum)的扩展,原来是一个和一个相对应,现在两两一组去进行判断,注意返回结果对重复值的剔除,对判断细节要注意。
26. Remove Duplicates from Sorted Array
Given a sorted array nums, remove the duplicates in-place such that each element appears only once and returns the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
Example 1:
1 | Input: nums = [1,1,2] |
Example 2:
1 | Input: nums = [0,0,1,1,1,2,2,3,3,4] |
Constraints:
0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums
is sorted in ascending order.
Solution:
1 | //一般解法可能是直接set,remove啥的 |
Note:
不要直接用builtin函数,注意
It doesn't matter what values are set beyond the returned length.
,就可以用以上的解法,只要找到所有的不重复数字,然后一个一个覆盖填充,剩下的部分无需理会。
27. Remove Element
Given an array nums and a value val, remove all instances of that value in-place and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
The order of elements can be changed. It doesn’t matter what you leave beyond the new length.
Example 1:
1 | Input: nums = [3,2,2,3], val = 3 |
Constraints:
0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100
Solution:
1 | func removeElement(nums []int, val int) int { |
Note:
………看不到用什么好方法,直接剔除重复部分,再把重复部分的两边粘起来:pensive:
33. Search in Rotated Sorted Array
You are given an integer array nums
sorted in ascending order, and an integer target
.
Suppose that nums
is rotated at some pivot unknown to you beforehand (i.e., [0,1,2,4,5,6,7]
might become [4,5,6,7,0,1,2]
).
If target
is found in the array return its index, otherwise, return -1
.
Example 1:
1 | Input: nums = [4,5,6,7,0,1,2], target = 0 |
Example 2:
1 | Input: nums = [4,5,6,7,0,1,2], target = 3 |
Example 3:
1 | Input: nums = [1], target = 0 |
Constraints:
1 <= nums.length <= 5000
-10^4 <= nums[i] <= 10^4
- All values of
nums
are unique. nums
is guranteed to be rotated at some pivot.-10^4 <= target <= 10^4
Solution:
1 | func search(nums []int, target int) int { |
Note:
由于数组无论怎么打乱也是有序的,所以需要判断当前中点是否可能出在一个有序的半边,判断出哪个半边有序,随后再用
target
对其进行判断,再决定左右指针的移动。
34. Find First and Last Position of Element in Sorted Array
Given an array of integers nums
sorted in ascending order, find the starting and ending position of a given target
value.
If target
is not found in the array, return [-1, -1]
.
Follow up: Could you write an algorithm with O(log n)
runtime complexity?
Example 1:
1 | Input: nums = [5,7,7,8,8,10], target = 8 |
Example 2:
1 | Input: nums = [5,7,7,8,8,10], target = 6 |
Example 3:
1 | Input: nums = [], target = 0 |
Constraints:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums
is a non-decreasing array.-109 <= target <= 109
Solution:
1 | func searchRange(nums []int, target int) []int { |
Note:
没有什么有趣的方法,采用binary search进行搜索,只要一找到目标值,就以当前坐标为起点,利用左右指针开始移动,探求出左右边界值,得出结果
35. Search Insert Position
Given a sorted array of distinct integers and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.
Example 1:
1 | Input: nums = [1,3,5,6], target = 5 |
Example 2:
1 | Input: nums = [1,3,5,6], target = 0 |
Example 3:
1 | Input: nums = [1], target = 0 |
Constraints:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums
contains distinct values sorted in ascending order.-104 <= target <= 104
Solution:
1 | func searchInsert(nums []int, target int) int { |
Note:
采用binary search进行搜索,找到就返回,没找到判断一下插入位置
39. Combination Sum
Given an array of distinct integers candidates
and a target integer target
, return a list of all unique combinations of candidates
where the chosen numbers sum to target
. You may return the combinations in any order.
The same number may be chosen from candidates
an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
It is guaranteed that the number of unique combinations that sum up to target
is less than 150
combinations for the given input.
Example 1:
1 | Input: candidates = [2,3,5], target = 8 |
Solution:
1 | func combinationSum(candidates []int, target int) [][]int { |
Note:
back-tracing
方法,一件件拿,一件件放回,一开始觉得像是完全背包,后来又觉得不太对劲。另外注意golang
里的append和传参指针操作
40. Combination Sum II
Given a collection of candidate numbers (candidates
) and a target number (target
), find all unique combinations in candidates
where the candidate numbers sum to target
.
Each number in candidates
may only be used once in the combination.
Note: The solution set must not contain duplicate combinations.
Example 1:
1 | Input: candidates = [2,5,2,1,2], target = 5 |
Solution:
1 | func combinationSum2(candidates []int, target int) [][]int { |
Note:
back-tracing
方法。但是每个candidate
不是无限制取用了,所以跟上一题相比,每次recursive都要+1;另外,题目注明不得有重复结果,所以需要在操作时给出合适的判断条件,剔除重复值。
首先保证重复值相互邻近,方便判断,所以需要extra overhead去排序
使用排序后的
Int[]
去做类似的上题的操作,但是需要这么一条语句去判断if i == startIndex || candidates[i] != candidates[i-1]
该条语句可以这样理解,可以把
i == startIndex
的情况想成本轮起点的第一次,也即是之前组合与本轮第一个数字所形成的的组合,是第一次形成的组合,需要保证。而重复值的剔除则需要candidates[i] != candidates[i-1]
。举例,candidates=[1,2,2,2,5]
,target=5
。开始时以数字1作为起点开始for循环,首先判断了i == startIndex
,随后开始放入1,开始下一个递归,到了数字2,2此时也符合条件,进入到下一个2,这个时候结果满足了target
,开始放入结果集,此时count
已经不满足小于target
,所以本次第二个2开始的递归结束了,回到上一个2,此时comb里面是[1,2]
,继续向后遍历,此时第二个2和第三个2由于candidates[i] != candidates[i-1]
的限制,都被剔除了。也即是,如果现在已有1,2,那么距离target
只有一个2的差距,那么根据递归的特性,本轮肯定是在满足了target
而又返回到这里的,所以如果满足的时候使用的是第二个2,那么回到这一轮的时候,第二个2以及后面重复的2都不应该在作为新的结果放入结果集中。我一开始的判断语句武断地写为
if i>0 && candidates[i] != candidates[i-1]
,导致结果错误。如果使用这条错误语句,那么上面例子中的[1,2,2]
就不会出现,这是因为2,2就会重复。所以i == startIndex
很好的保证了某轮for
循环的第一个数字一定是可以被拿入来做进行组合的,在满足条件之后递归回到上一轮的时候,此时就不需要重复值了,因为如果是需要多个重复的x值去满足一个target
,那么最深处的某一轮一定是完全拿到了自己想要组合,余下的x只是重复的多余选择而已,不再需要。candidates[i] != candidates[i-1]
也就在此时发挥作用。
42. Trapping Rain Water
Given n
non-negative integers representing an elevation map where the width of each bar is 1
, compute how much water it can trap after raining.
Example 1:
1 | Input: height = [0,1,0,2,1,0,1,3,2,1,2,1] |
Example 2:
1 | Input: height = [4,2,0,3,2,5] |
Constraints:
n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105
Solution:
1 | func trap(height []int) int { |
Note:
受到LeetCode Discuss的教导,在上面贴上这种很巧妙地解题代码
curHigh
:当前的可行蓄水高度
curLow
:当前最低处高度注意图上的y轴是无法作为墙的,所以[0,1….]这里没有办法蓄积到水
思路如下,左右各有一个指针。根据题目描述,囤积的雨水数量一定与最低的一边有关,所以开始遍历时,先判断左右两边指针所指向的的高度孰高孰低。用以下数据为例[9, 8, 2, 6],一开始指针指向9和6,此时6比9小,6就赋给了
curHigh
和curLow
,此时curHigh
可以安全地置为6,这是因为6属于小的一方,以6为最大高度囤积雨水,另一侧一定有一个更高的高度来兜底,导致雨水可以被囤积;r指针随后移动到了数字2,2与9比较,还是2小,所以2现在是整个数组中的最低洼,curLow=2
,而当前curHigh=6
,所以此时的水囤积为4,这里只考虑当前低洼处单体所可以积蓄的水量,而不用考虑两边的延伸。当r继续移动后,值8就要比当前的curHigh
要大了,所以需要进行一次数值更新,而由于更新后l已经等于了r,本次计算就结束了。再以[2, 1, 5, 4, 1, 3]为例,一开始左右比较,值2比4小,从左指针向右靠拢,2变成最高处与最低处,l指针移动到1,1与2形成的积水量为1,总量加1,再继续移动到值5,5比3要大,此时也就代表以2为左起点的蓄水面积已经到头了,也即高度为2的蓄水部分此时已经无法漫过当前的l指针指向的高度。所以实际上此时的左起点高度变为5,需要从右指针开始向左靠拢。当前可蓄水高度变为3,低洼处也被置为3;进入下一轮,l处值还是比r处大,
curLow
被置为1,此时高度1与高度3形成了单位2的蓄水量,总量再加2;最后一轮,r指针指向4,4依旧小于5,4重新被置为最低处值,从代码上来考虑,curHigh = max(curHigh, curLow)
又保证了一旦low大于或等于原先的high,low与high就会相等,他们的差值就会变为0,不会影响到总结果;从实际上考虑,此时右边的起点也就换了,因为3为高度的蓄水区域依旧无法漫过高度4这个位置了,所以4将会成为新的右边界,而此时l与r指针已经相遇,4与5又是紧贴,2个高度是无法蓄积到水的,所以本次循环结束。总结:该思路通过左右指针的移动找到当前数组里的蓄水池可行高度,并且将目标着眼于每个遍历到的高度与当前可行高度的差值,继而得出当前高度可以贡献多少的蓄水量,可以形象的想象成,他只考虑每个高度上现在能存多少水,如同空中楼阁一般立在那里,等到整个遍历结束,每个空中楼阁合在一起就变成了完整的蓄水池。
45. Jump Game II
Given an array of non-negative integers nums
, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
You can assume that you can always reach the last index.
Example 1:
1 | Input: nums = [2,3,1,1,4] |
Example 2:
1 | Input: nums = [2,3,0,1,4] |
Constraints:
1 <= nums.length <= 3 * 104
0 <= nums[i] <= 105
Solution:
1 | func jump(nums []int) int { |
Note:
Related Topics提示是greedy,但是巧妙的思路应该是这样的,遍历数组,对每一个遍历到每一个点所可以跳跃的最远距离做一次比较记录,而不去逐一考虑该点的每种情况。
以[2,3,1,1,4]为例,开始时首先在2的位置,此时可以选择跳2步,或者跳1步,根据以上思想,我们只看现在的位置可以到达的最远距离,值为
i+step=0+2=2
,也即是当前点最远可以到index=2的1处,而此时i == curEnd
,jump就需要加1,也即代表从2到3,1这些范围的区域,最少只需要一步,curEnd此时也等于2(index);之后遍历到第二个点,此时curFar = max(i+step, curFar)
得出的值是3+1=4, (4就是最后的终点)。但是此时的index并没有等于curEnd
,所以此轮只更新curFar
,到第三轮的时候,i=curEnd
,此时我们可以发现,curFar==4
,这表示在该点之前,就已经有一个点可以跳到终点,而由于那个点的index肯定小于当前index,所以那个点一定是在当前的jump
数内可达的,但是此时curEnd的值并不等于终点,也即所以要想跳到终点,总的jump
数一定是先到达那个点,随后再通过那个点跳到终点,所以jump++
if curEnd == len(nums)-1 {...}
保证jump
不会多计数(针对开头一步就跳到终点的情况每个
jump
下的curEnd
一定是当前jump
时,所能够达到的最远距离,也是最接近终点的距离
48. Rotate Image
You are given an n x n 2D matrix
representing an image, rotate the image by 90 degrees (clockwise).
You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.
Example 1:
1 | Input: matrix = [[1,2,3],[4,5,6],[7,8,9]] |
Constraints:
matrix.length == n
matrix[i].length == n
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000
Solution:
1 | func rotate(matrix [][]int) { |
Note:
90度顺时针旋转可以由分解为以下过程(建立在n x n的matrix的基础上) ,沿对角线的对应元素置换,即i==j的对角线上的元素不动,x行y列与y行x列元素相交换,随后沿着垂直中心轴,再镜像翻转,倒数第一列与第一列置换,倒数第二列与第二列置换
53. Maximum Subarray
Given an integer array nums
, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Follow up: If you have figured out the O(n)
solution, try coding another solution using the divide and conquer approach, which is more subtle.
Example 1:
1 | Input: nums = [-2,1,-3,4,-1,2,1,-5,4] |
Given an array of non-negative integers nums
, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Your goal is to reach the last index in the minimum number of jumps.
You can assume that you can always reach the last index.
Example 1:
1 | Input: nums = [2,3,1,1,4] |
Example 2:
1 | Input: nums = [2,3,0,1,4] |
Constraints:
1 <= nums.length <= 3 * 104
0 <= nums[i] <= 105
Solution:
1 | func maxSubArray(nums []int) int { |
Note:
dp思想,dp[i]等于前i个元素中所可以组成的连续序列的最大值,一开始dp[0] (index为0,实则为第一个元素)它的最大值就是它本身,注意题目要求必须选择有一个元素,所以dp[0]赋值为nums[0]就是为了确保nums只有一个元素的情况下也可以正确返回结果,随后我们要判断
dp[i-1]
与0的大小,也即是当前的dp[i]需要参考i-1个元素形成的结果,如果他们形成的最大值是负数,那么舍去负数一定是正确的,负的dp[i-1]对之后的结果不会存在正向帮助,任何组合加上负数一定会变小,此时需要重新以nums[i]开始一个新的序列。一个nums里如果全部是负数,那么最大的序列就是找到最小的负数,并且它们在上面的for循环中也无法形成任何一个连续的序列。