outline
例题1.Find Peak Element
A peak element is an element that is greater than its neighbors.
Given an input array where
num[i] ≠ num[i+1]
, find a peak element and return its index.The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.
You may imagine that
num[-1] = num[n] = -∞
.For example, in array
[1, 2, 3, 1]
, 3 is a peak element and your function should return the index number 2.
找局部最大值。
思路:
baseline:
遍历,找到i:nums[i-1]<num[i]<num[i+1]
复杂度
优化:二分法
首先我们找到中间节点mid,如果大于两边返回当前index就可以了,如果左边的节点比mid大,那么我们可以继续在左半区间查找,这里面一定存在一个peak,为什么这么说呢?假设此时的区间范围为[0, mid - 1], 因为num[mid - 1]一定大于num[mid]了,如果num[mid - 2] <= num[mid - 1],那么num[mid - 1]就是一个peak。如果num[mid - 2] > num[mid - 1],那么我们就继续在[0, mid - 2]区间查找,因为num[-1]为负无穷,所以最终我们绝对能在左半区间找到一个peak。同理右半区间一样。
复杂度
代码:
|
follow up: Find Peak Element II
由一维拓展到二维,在矩阵上找peak element
peak element:matrix[i][j]
比其上下左右相邻元素大
思路:
baseline:
遍历
复杂度复杂度
优化:二分法
- 找到中间行的最大值
matrix[i][j]
- 跟相邻上下元素比较,决定向上/向下走
- 如果上面的元素比较大,向上走,否则向下走
复杂度
- 找到中间行的最大值
优化:行列交替二分
- 找到中间行的最大值
matrix[i][j]
- 跟相邻上下元素比较,决定向上/向下走 剩下一半矩阵
- 找中间列的最大值
matrix[i][j]
- 跟相邻左右元素比较,决定向左/向右走 剩下n/4矩阵
复杂度
- 找到中间行的最大值
例题2. Subarray Sum
Given an integer array, find a subarray where the sum of numbers is zero. Your code should return the index of the first number and the index of the last number.
Example
Given
[-3, 1, 2, -3, 4]
, return[0, 2]
or[1, 3]
.
找子数组,和为0
思路:
baseline:
两指针遍历
复杂度复杂度
prefix sum:
用hash表记录前缀和的取值
|
follow up 1: Submatrix Sum
Given an integer matrix, find a submatrix where the sum of numbers is zero. Your code should return the coordinate of the left-up and right-down number.
Example
Given matrix
> [> [1 ,5 ,7],> [3 ,7 ,-8],> [4 ,-8 ,9],> ]>>
>
return
[(1,1), (2,2)]
求元素和为0的子矩阵,返回矩阵的左上角和右下角元素位置
思路:
先定位子矩阵的首行和尾行(外层循环)
把首行和尾行之间的元素压成一行,变成一个数组
对上面的数组做subarray sum,找到和为0的子数组就可以定位子矩阵的首列和尾列。
预计算presum矩阵:
presum[i][j] = matrix[0][0]到matrix[i][j]的所有元素和
当外层循环固定为l和h时,内层循环j从0开始遍历,矩阵的前缀和为presum[h][j]-presum[l][j]
代码:
|
follow up 2: Subarray Sum II
给定一个数组nums和一个区间interval,返回nums数组中和在区间interval中的子数组个数,如nums = [1,2,3,4],interval = [1,3],return 4,the possible answers are:[0,0],[0,1],[1,1],[2,2]
思路:
low < prefix[j] - prefix[i] < high
low + prefix[i] < prefix[j] < high + prefix[i]
prefix[i] < prefix[j] - low
prefix[i] > prefix[j] - high
所以本题就是要找到在[prefix[j] - high , prefix[j] - low]范围内的prefix[i]
由于prefix[i]是递增的,所以可以存在数组中,用二分法查找
例题3. Maximum Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array
[-2,1,-3,4,-1,2,1,-5,4]
,
the contiguous subarray[4,-1,2,1]
has the largest sum =6
.
找和最大的子数组
思路:
方法1:prefixsum
维护最小的prefixsum和当前最大的子数组和
方法2:dp
dp[i] = max(dp[i-1] + num[i],num[i])
代码:
|
follow up 循环连续子数组
上题的数组变成循环数组。
处理循环数组三种方法:
- 拆开
- 扩展
- 取反
分别看对于这道题是否可行:
拆开
house robber用到了这个方法,抢第一个就不能抢最后一个,抢最后一个就不能抢第一个
扩展
将数组翻一倍,[-3, 1, 3, -3, 4]变成[-3, 1, 3, -3, 4,-3,1,3,-3],然后找最大子数组,但是长度不能超过nums的长度。
取反
找循环数组中的最大子数组,有两种情况:
- 在数组的中部,正常找就行了
- 一半在数组后面,一半在数组头部,因为数组的总和是一定的,因此这种情况可以转化成在数组中部找最小的子数组
然后取上面两种情况的最大值。
例题4. Wiggle Sort
Given an unsorted array
nums
, reorder it in-place such thatnums[0] <= nums[1] >= nums[2] <= nums[3]...
.For example, given
nums = [3, 5, 2, 1, 6, 4]
, one possible answer is[1, 6, 2, 5, 3, 4]
.
代码:
|
follow up Wiggle Sort II
Given an unsorted array
nums
, reorder it such thatnums[0] < nums[1] > nums[2] < nums[3]...
.Example:
(1) Givennums = [1, 5, 1, 1, 6, 4]
, one possible answer is[1, 4, 1, 5, 1, 6]
.
(2) Givennums = [1, 3, 2, 2, 3, 1]
, one possible answer is[2, 3, 1, 3, 1, 2]
.
思路:
baseline:
对数组排序,排序之后将数组分成大小两堆,然后依次选取排序
quick sort思想
利用quick sort 找到中点,然后对左右两边元素一次选取排序
代码:
|
例题5. Building Post Office Best Meeting Point
A group of two or more people wants to meet and minimize the total travel distance. You are given a 2D grid of values 0 or 1, where each 1 marks the home of someone in the group. The distance is calculated using Manhattan Distance, where distance(p1, p2) =
|p2.x - p1.x| + |p2.y - p1.y|
.For example, given three people living at
(0,0)
,(0,4)
, and(2,2)
:
> 1 - 0 - 0 - 0 - 1> | | | | |> 0 - 0 - 0 - 0 - 0> | | | | |> 0 - 0 - 1 - 0 - 0>
>
The point
(0,2)
is an ideal meeting point, as the total travel distance of 2+2+2=6 is minimal. So return 6.
思路:
baseline:
遍历所有位置,计算每个位置到所有人的距离,取最小的
优化:
看成一维,对于所有人来说,meeting point选在所有人的中位数的位置距离和最近,因此对行和列坐标分别选取中位数,得到meeting point
代码:
|
follow up1. Shortest Distance from All Buildings
You want to build a house on an empty land which reaches all buildings in the shortest amount of distance. You can only move up, down, left and right. You are given a 2D grid of values 0, 1 or 2, where:
- Each 0 marks an empty land which you can pass by freely.
- Each 1 marks a building which you cannot pass through.
- Each 2 marks an obstacle which you cannot pass through.
For example, given three buildings at
(0,0)
,(0,4)
,(2,2)
, and an obstacle at(0,2)
:
> 1 - 0 - 2 - 0 - 1> | | | | |> 0 - 0 - 0 - 0 - 0> | | | | |> 0 - 0 - 1 - 0 - 0>
>
The point
(1,2)
is an ideal empty land to build a house, as the total travel distance of 3+3+1=7 is minimal. So return 7.
思路:
baseline:
bfs,计算每个点到所有人的距离,取距离和最小的
时间复杂度:外层循环 然后内层bfs,因此时间复杂度
反向bfs
计算每个人到所有位置的距离
dis[k][i][j]
,复杂度然后再遍历矩阵中每一个点,查询距离,取最小值,复杂度
因此时间复杂度
代码:
|
follow up 2. Bomb Enemy
Given a 2D grid, each cell is either a wall
'W'
, an enemy'E'
or empty'0'
(the number zero), return the maximum enemies you can kill using one bomb.
The bomb kills all the enemies in the same row and column from the planted point until it hits the wall since the wall is too strong to be destroyed.
Note that you can only put the bomb at an empty cell.Example:
> For the given grid>> 0 E 0 0> E 0 W E> 0 E 0 0>> return 3. (Placing a bomb at (1,1) kills 3 enemies)>
思路:
baseline:
bfs,计算每个点能够炸到的到所有人
时间复杂度:外层循环 然后内层,因此时间复杂度
反向bfs
申请四个数组:
left[i][j]:在(i,j)放炸弹,向左最多炸人数
right[i][j]:在(i,j)放炸弹,向右最多炸人数
up[i][j]:在(i,j)放炸弹,向上最多炸人数
dowm[i][j]:在(i,j)放炸弹,向下最多炸人数
将四个数组相加就得到在(i,j)放炸弹,总共炸人数
因此时间复杂度
代码:
|
例题6. N个数组的第K大问题
在N个数组中找到第K大的元素
排序+heap
类似merge K sorted list