2021-12-28:给定一个二维数组matrix,matrix[i][j] = k代表: 从(i,j)位置可以随意往右跳<=k步,或者从(i,j)位置可以随意往下跳<=k步, 如果matrix[i]
Posted 福大大架构师每日一题
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-12-28:给定一个二维数组matrix,matrix[i][j] = k代表: 从(i,j)位置可以随意往右跳<=k步,或者从(i,j)位置可以随意往下跳<=k步, 如果matrix[i]相关的知识,希望对你有一定的参考价值。
2021-12-28:给定一个二维数组matrix,matrix[i][j] = k代表:
从(i,j)位置可以随意往右跳<=k步,或者从(i,j)位置可以随意往下跳<=k步,
如果matrix[i][j] = 0,代表来到(i,j)位置必须停止,
返回从matrix左上角到右下角,至少要跳几次,
已知matrix中行数n <= 5000, 列数m <= 5000,
matrix中的值,<= 5000。
来自京东。
答案2021-12-28:
方法一:自然智慧。递归。复杂度过不了。
方法二:动态规划+线段树。
代码用golang编写。代码如下:
package main
import (
"fmt"
"math"
)
func main()
ret := jump2([][]int1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
fmt.Println(ret)
func getMin(a, b int) int
if a < b
return a
else
return b
// 优化方法, 利用线段树做枚举优化
// 因为线段树,下标从1开始
// 所以,该方法中所有的下标,请都从1开始,防止乱!
func jump2(arr [][]int) int
n := len(arr)
m := len(arr[0])
map0 := make([][]int, n+1)
for i := 0; i < n+1; i++
map0[i] = make([]int, m+1)
for a, b := 0, 1; a < n; a, b = a+1, b+1
for c, d := 0, 1; c < m; c, d = c+1, d+1
map0[b][d] = arr[a][c]
rowTrees := make([]*SegmentTree, n+1)
for i := 1; i <= n; i++
rowTrees[i] = NewSegmentTree(m)
colTrees := make([]*SegmentTree, m+1)
for i := 1; i <= m; i++
colTrees[i] = NewSegmentTree(n)
rowTrees[n].update0(m, m, 0, 1, m, 1)
colTrees[m].update0(n, n, 0, 1, n, 1)
for col := m - 1; col >= 1; col--
if map0[n][col] != 0
left := col + 1
right := getMin(col+map0[n][col], m)
next := rowTrees[n].query(left, right, 1, m, 1)
if next != math.MaxInt64
rowTrees[n].update0(col, col, next+1, 1, m, 1)
colTrees[col].update0(n, n, next+1, 1, n, 1)
for row := n - 1; row >= 1; row--
if map0[row][m] != 0
up := row + 1
down := getMin(row+map0[row][m], n)
next := colTrees[m].query(up, down, 1, n, 1)
if next != math.MaxInt64
rowTrees[row].update0(m, m, next+1, 1, m, 1)
colTrees[m].update0(row, row, next+1, 1, n, 1)
for row := n - 1; row >= 1; row--
for col := m - 1; col >= 1; col--
if map0[row][col] != 0
// (row,col) 往右是什么范围呢?[left,right]
left := col + 1
right := getMin(col+map0[row][col], m)
next1 := rowTrees[row].query(left, right, 1, m, 1)
// (row,col) 往下是什么范围呢?[up,down]
up := row + 1
down := getMin(row+map0[row][col], n)
next2 := colTrees[col].query(up, down, 1, n, 1)
next := getMin(next1, next2)
if next != math.MaxInt64
rowTrees[row].update0(col, col, next+1, 1, m, 1)
colTrees[col].update0(row, row, next+1, 1, n, 1)
return rowTrees[1].query(1, 1, 1, m, 1)
// 区间查询最小值的线段树
// 注意下标从1开始,不从0开始
// 比如你传入size = 8
// 则位置对应为1~8,而不是0~7
type SegmentTree struct
min []int
change []int
update []bool
func NewSegmentTree(size int) *SegmentTree
ret := &SegmentTree
N := size + 1
ret.min = make([]int, N<<2)
ret.change = make([]int, N<<2)
ret.update = make([]bool, N<<2)
ret.update0(1, size, math.MaxInt64, 1, size, 1)
return ret
func (this *SegmentTree) pushUp(rt int)
this.min[rt] = getMin(this.min[rt<<1], this.min[rt<<1|1])
func (this *SegmentTree) pushDown(rt, ln, rn int)
if this.update[rt]
this.update[rt<<1] = true
this.update[rt<<1|1] = true
this.change[rt<<1] = this.change[rt]
this.change[rt<<1|1] = this.change[rt]
this.min[rt<<1] = this.change[rt]
this.min[rt<<1|1] = this.change[rt]
this.update[rt] = false
// 最后三个参数是固定的, 每次传入相同的值即可:
// l = 1(固定)
// r = size(你设置的线段树大小)
// rt = 1(固定)
func (this *SegmentTree) update0(L, R, C, l, r, rt int)
if L <= l && r <= R
this.update[rt] = true
this.change[rt] = C
this.min[rt] = C
return
mid := (l + r) >> 1
this.pushDown(rt, mid-l+1, r-mid)
if L <= mid
this.update0(L, R, C, l, mid, rt<<1)
if R > mid
this.update0(L, R, C, mid+1, r, rt<<1|1)
this.pushUp(rt)
// 最后三个参数是固定的, 每次传入相同的值即可:
// l = 1(固定)
// r = size(你设置的线段树大小)
// rt = 1(固定)
func (this *SegmentTree) query(L, R, l, r, rt int) int
if L <= l && r <= R
return this.min[rt]
mid := (l + r) >> 1
this.pushDown(rt, mid-l+1, r-mid)
left := math.MaxInt64
right := math.MaxInt64
if L <= mid
left = this.query(L, R, l, mid, rt<<1)
if R > mid
right = this.query(L, R, mid+1, r, rt<<1|1)
return getMin(left, right)
执行结果如下:
以上是关于2021-12-28:给定一个二维数组matrix,matrix[i][j] = k代表: 从(i,j)位置可以随意往右跳<=k步,或者从(i,j)位置可以随意往下跳<=k步, 如果matrix[i]的主要内容,如果未能解决你的问题,请参考以下文章
2022-06-25:给定一个正数n, 表示有0~n-1号任务, 给定一个长度为n的数组time,time[i]表示i号任务做完的时间, 给定一个二维数组matrix, matrix[j] = {a,
递归之求二维数组的最短路径给定一个整数和一个数组任意选择数组中的数累加能否得到该整数
2022-09-25:给定一个二维数组matrix,数组中的每个元素代表一棵树的高度。 你可以选定连续的若干行组成防风带,防风带每一列的防风高度为这一列的最大值 防风带整体的防风高度为,所有列防风高度