文章目录
5271. 访问所有点的最小时间
题目描述
平面上有 n
个点,点的位置用整数坐标表示 points[i] = [xi, yi]
。请你计算访问所有这些点需要的最小时间(以秒为单位)。
你可以按照下面的规则在平面上移动:
- 每一秒沿水平或者竖直方向移动一个单位长度,或者跨过对角线(可以看作在一秒内向水平和竖直方向各移动一个单位长度)。
- 必须按照数组中出现的顺序来访问这些点。
示例 1:
输入:points = [[1,1],[3,4],[-1,0]]
输出:7
解释:一条最佳的访问路径是: [1,1] -> [2,2] -> [3,3] -> [3,4] -> [2,3] -> [1,2] -> [0,1] -> [-1,0]
从 [1,1] 到 [3,4] 需要 3 秒
从 [3,4] 到 [-1,0] 需要 4 秒
一共需要 7 秒
示例 2:
输入:points = [[3,2],[-2,2]]
输出:5
提示:
points.length == n
1 <= n <= 100
points[i].length == 2
-1000 <= points[i][0], points[i][1] <= 1000
Tag
- 可跨对角线移动,即可在一秒内向水平和竖直方向各移动一个单位长度,所以两点之间移动最少时间为 m a x { d x , d y } max \{dx, dy\} max{dx,dy}
- 时间: O ( n ) O(n) O(n),空间: O ( 1 ) O(1) O(1)
Code
go version
func minTimeToVisitAllPoints(points [][]int) int {
minTime := 0
for i := 0; i < len(points)-1; i++ {
dx := points[i][0]-points[i+1][0]
dy := points[i][1]-points[i+1][1]
if dx < 0 {
dx = ^dx + 1
}
if dy < 0 {
dy = ^dy + 1
}
minTime += max(dx, dy)
}
return minTime
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
5272. 统计参与通信的服务器
题目描述
这里有一幅服务器分布图,服务器的位置标识在 m * n
的整数矩阵网格 grid
中,1 表示单元格上有服务器,0 表示没有。
如果两台服务器位于同一行或者同一列,我们就认为它们之间可以进行通信。
请你统计并返回能够与至少一台其他服务器进行通信的服务器的数量。
示例 1:
输入:grid = [[1,0],[0,1]]
输出:0
解释:没有一台服务器能与其他服务器进行通信。
示例 2:
输入:grid = [[1,0],[1,1]]
输出:3
解释:所有这些服务器都至少可以与一台别的服务器进行通信。
示例 3:
输入:grid = [[1,1,0,0],[0,0,1,0],[0,0,1,0],[0,0,0,1]]
输出:4
解释:第一行的两台服务器互相通信,第三列的两台服务器互相通信,但右下角的服务器无法与其他服务器通信。
提示:
m == grid.length
n == grid[i].length
1 <= m <= 250
1 <= n <= 250
grid[i][j] == 0 or 1
Tag
- 某单元格有服务器,且所在行或列服务器数大于1,则 c n t + 1 cnt + 1 cnt+1
- 时间: O ( m ∗ n ) O(m*n) O(m∗n),空间: O ( n + m ) O(n + m) O(n+m)
Code
go version
func countServers(grid [][]int) int {
// exists := make([][]bool, len(grid))
// for i := 0; i < len(grid); i++ {
// exists[i] = make([]bool, len(grid[0]))
// }
row := make([]int, len(grid))
col := make([]int, len(grid[0]))
cnt := 0
for i := 0; i < len(grid); i++ {
for j := 0; j < len(grid[0]); j++ {
if grid[i][j] == 1 {
row[i] += 1
col[j] += 1
}
}
}
for i := 0; i < len(grid); i++ {
for j := 0; j < len(grid[0]); j++ {
if grid[i][j] == 1 && (row[i] > 1 || col[j] > 1) { // 定义
cnt += 1
}
}
}
return cnt
}
5273. 搜索推荐系统
题目描述
给你一个产品数组 products
和一个字符串 searchWord
,products
数组中每个产品都是一个字符串。
请你设计一个推荐系统,在依次输入单词 searchWord
的每一个字母后,推荐 products
数组中前缀与 searchWord
相同的最多三个产品。如果前缀相同的可推荐产品超过三个,请按字典序返回最小的三个。
请你以二维列表的形式,返回在输入 searchWord
每个字母后相应的推荐产品的列表。
示例 1:
输入:products = ["mobile","mouse","moneypot","monitor","mousepad"], searchWord = "mouse"
输出:[
["mobile","moneypot","monitor"],
["mobile","moneypot","monitor"],
["mouse","mousepad"],
["mouse","mousepad"],
["mouse","mousepad"]
]
解释:按字典序排序后的产品列表是 ["mobile","moneypot","monitor","mouse","mousepad"]
输入 m 和 mo,由于所有产品的前缀都相同,所以系统返回字典序最小的三个产品 ["mobile","moneypot","monitor"]
输入 mou, mous 和 mouse 后系统都返回 ["mouse","mousepad"]
示例 2:
输入:products = ["havana"], searchWord = "havana"
输出:[["havana"],["havana"],["havana"],["havana"],["havana"],["havana"]]
示例 3:
输入:products = ["bags","baggage","banner","box","cloths"], searchWord = "bags"
输出:[["baggage","bags","banner"],["baggage","bags","banner"],["baggage","bags"],["bags"]]
示例 4:
输入:products = ["havana"], searchWord = "tatiana"
输出:[[],[],[],[],[],[],[]]
提示:
1 <= products.length <= 1000
1 <= Σ products[i].length <= 2 * 10^4
products[i]
中所有的字符都是小写英文字母。1 <= searchWord.length <= 1000
searchWord
中所有字符都是小写英文字母。
Tag
- 每次匹配后的列表作为新的列表遍历,同时注意字符比较时越界问题,以及隐藏的一个坑(见代码)
- 时间: O ( l e n ( s e a r c h W o r d ) ∗ O(len(searchWord)* O(len(searchWord)∗ ∑ l e n ( p r o d u c t [ i ] ) \sum len(product[i]) ∑len(product[i]) ) ) ),空间: O ( O( O( ∑ l e n ( p r o d u c t [ i ] ) ) \sum len(product[i])) ∑len(product[i]))
Code
go version
func suggestedProducts(products []string, searchWord string) [][]string {
ans := [][]string{}
toMatch := products // 新的切片对象(不使用copy)
sorted := false
for i, character := range searchWord {
curMatch := []string{}
for _, product := range toMatch {
if i < len(product) && rune(product[i]) == character { // byte转化为rune
curMatch = append(curMatch, product)
}
}
toMatch = curMatch // 更新下一次匹配的列表
if !sorted { // 坑:case实际要求推荐产品不超过3时也按字典序返回
sort.Strings(curMatch) // 字典序排序
sorted = true
}
if len(curMatch) > 3 {
// sort.Strings(curMatch) // 字典序排序
curMatch = curMatch[0:3] // 字典序最小的三个产品
}
ans = append(ans, curMatch) // 每次获得一个推荐列表(切片数组)
}
return ans
}
5274. 停在原地的方案数
题目描述
有一个长度为 arrLen
的数组,开始有一个指针在索引 0
处。
每一步操作中,你可以将指针向左或向右移动 1 步,或者停在原地(指针不能被移动到数组范围外)。
给你两个整数 steps
和 arrLen
,请你计算并返回:在恰好执行 steps
次操作以后,指针仍然指向索引 0
处的方案数。
由于答案可能会很大,请返回方案数 模 10^9 + 7
后的结果。
示例 1:
输入:steps = 3, arrLen = 2
输出:4
解释:3 步后,总共有 4 种不同的方法可以停在索引 0 处。
向右,向左,不动
不动,向右,向左
向右,不动,向左
不动,不动,不动
示例 2:
输入:steps = 2, arrLen = 4
输出:2
解释:2 步后,总共有 2 种不同的方法可以停在索引 0 处。
向右,向左
不动,不动
示例 3:
输入:steps = 4, arrLen = 2
输出:8
提示:
1 <= steps <= 500
1 <= arrLen <= 10^6
Tag
- d p [ i ] [ j ] dp[i][j] dp[i][j]: 指针移动 j j j 步最终到达索引 i i i 的方案数,由于指针有向左、向右、不动三种选择,则:
d p [ i ] [ j ] = { d p [ i ] [ j − 1 ] + d p [ i + 1 ] [ j − 1 ] i f i = 0 d p [ i ] [ j − 1 ] + d p [ i − 1 ] [ j − 1 ] i f i = l e n − 1 d p [ i ] [ j − 1 ] + d p [ i + 1 ] [ j − 1 ] + d p [ i − 1 ] [ j − 1 ] o t h e r s dp[i][j] =\begin{cases} dp[i][j-1] + dp[i+1][j-1] & if~~i = 0 \\ dp[i][j-1] + dp[i-1][j-1] & if~~i = len-1 \\ dp[i][j-1] + dp[i+1][j-1] + dp[i-1][j-1] & others \end{cases} dp[i][j]=⎩⎪⎨⎪⎧dp[i][j−1]+dp[i+1][j−1]dp[i][j−1]+dp[i−1][j−1]dp[i][j−1]+dp[i+1][j−1]+dp[i−1][j−1]if i=0if i=len−1others
- 优化-——时间: O ( min ( s t e p s / 2 + 1 , a r r L e n ) ∗ s t e p s ) O(\min(steps/2+1, arrLen)*steps) O(min(steps/2+1,arrLen)∗steps),空间: O ( min ( s t e p s / 2 + 1 , a r r L e n ) ∗ s t e p s ) O(\min(steps/2+1, arrLen)*steps) O(min(steps/2+1,arrLen)∗steps)
Code
go version
const P = 1e9 + 7
func numWays(steps int, arrLen int) int {
if min(steps/2+1, arrLen) == 1 {
return 1
}
// dp数组的第一维不能超过steps/2+1,否则无法返回原索引点0
dp := make([][]int, min(steps/2+1, arrLen))
for i := 0; i < len(dp); i++ {
dp[i] = make([]int, steps+1)
}
dp[0][0] = 1 // dp[1...][0] = 0
for j := 1; j <= steps; j++ {
dp[0][j] = (dp[0][j-1] + dp[1][j-1])%P
for i := 1; i < len(dp)-1; i++ {
dp[i][j] = ((dp[i][j-1] + dp[i+1][j-1])%P + dp[i-1][j-1])%P
}
dp[len(dp)-1][j] = (dp[len(dp)-1][j-1] + dp[len(dp)-2][j-1])%P
}
return dp[0][steps]
}
func min(a, b int) int {
if a < b {
return a
}
return b
}