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([][]int{{1, 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)
}

执行结果如下:


左神java代码

2021-12-28:给定一个二维数组matrix,matrix[i][j] = k代表: 从(i,j)位置可以随意往右跳<=k步,或者从(i,j)位置可以随意往下跳<=k步, 如果matrix[i]的更多相关文章

  1. ytu 1050:写一个函数,使给定的一个二维数组(3×3)转置,即行列互换(水题)

    1050: 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 154  Solved: 112[ ...

  2. c语言题目:找出一个二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小。也可能没有鞍点

    //题目:找出一个二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小.也可能没有鞍点. // #include "stdio.h" #include <stdli ...

  3. C#编写程序,找一找一个二维数组中的鞍点

    编写程序,找一找一个二维数组中的鞍点(即该位置上的元素值在行中最大,在该列上最小.有可能数组没有鞍点).要求: 1.二维数组的大小.数组元素的值在运行时输入: 2.程序有友好的提示信息. 代码: us ...

  4. [CareerCup] 13.10 Allocate a 2D Array 分配一个二维数组

    13.10 Write a function in C called my2DAlloc which allocates a two-dimensional array. Minimize the n ...

  5. new一个二维数组

    .定义一个二维数组 char **array1 array1 = new char *[x]; for(i=0;i<x;++i) array1[i] = new char[y]; ...用的时候 ...

  6. php中向前台js中传送一个二维数组

    在php中向前台js中传送一个二维数组,并在前台js接收获取其中值的全过程方法: (1),方法说明:现在后台将数组发送到前台 echo json_encode($result); 然后再在js页面中的 ...

  7. JAVA生成一个二维数组,使中间元素不与相邻的9个元素相等,并限制每一个元素的个数

    JAVA生成一个二维数组,使中间元素不与相邻的9个元素相等,并限制每一个元素的个数 示例如下 至少需要九个元素:"A","B","C",&q ...

  8. 如何用一个for循环打印出一个二维数组

    思路分析: 二维数组在内存中默认是按照行存储的,比如一个二维数组{{1,2,3,},{4,5,6}},它在内存中存储的顺序就是1.2.3.4.5.6,也就是说,对于这6个数组元素,按照从0到5给它们编 ...

  9. C语言程序,找出一个二维数组的鞍点。

    什么是鞍点????? 鞍点就是在一个二维数组中,某一个数在该行中最大,然而其在该列中又是最小的数,这样的数称为鞍点. 昨天突然在书上看到这样的一道题,就自己尝试着写了一个找出一个二维数组中的鞍点. 好 ...

  10. <转载>c++中new一个二维数组

    原文连接 在c++中定义一个二维数组时有多种方式,下面是几种定义方式的说明:其中dataType 表示数据类型,如int  byte  long... 1.dataType (*num)[n] = n ...

随机推荐

  1. Arduino优化 减少重复代码 例2

    Example->Blink: void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUI ...

  2. 【LeetCode回溯算法#06】复原IP地址详解(练习如何处理边界条件,判断IP合法性)

    复原IP地址 力扣题目链接(opens new window) 给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式. 有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 ...

  3. 一篇博客带你学会MyBatis

    概念 MyBatis是一款持久层框架,用于简化JDBC操作(JavaEE三层架构:表现层(用来做页面的代码),业务层(业务逻辑代码),持久层(对数据库操作的代码))(框架就是一个半成品软件,是一套可重 ...

  4. 痞子衡嵌入式:我为2021 TencentOS Tiny AIoT应用创新大赛做了场直播培训

    TencentOS Tiny AIoT 应用创新大赛是腾讯 TencentOS 团队联合恩智浦半导体.安谋科技(Arm China)发起的线上开发者活动,主要面向中小企业嵌入式工程师.广大嵌入式开发者 ...

  5. 自己动手从零写桌面操作系统GrapeOS系列教程——13.向MBR中写入程序

    学习操作系统原理最好的方法是自己写一个简单的操作系统. 前面铺垫了这么久,今天终于开始写程序了.本讲将介绍3个逐步深入但非常简单的程序,一方面是让大家熟悉开发流程,另一方面是顺便解决前面遇到的CPU占 ...

  6. Nacos的微服务与本地测试的问题

    前提条件: 这里是微服务上的yml的配置: uri: base-svc-authcenter: 192.168.1.121:28002 base-svc-file: 192.168.1.121:280 ...

  7. swiper.js Bscroll 轮播

    <!-- 轮播banner图 --> <div class="banner"> <div class="swiper-container&q ...

  8. ServiceAccounts 及 Secrets 重大变化

    关于 ServiceAccounts 及其 Secrets 的重大变化 kubernetes v1.24.0 更新之后进行创建 ServiceAccount 不会自动生成 Secret 需要对其手动创 ...

  9. defineProperty在数据劫持后是如何通知数据的更新和视图的更新的

    vue的双向绑定是由数据劫持结合发布者-订阅者模式实现的,那么什么是数据劫持?vue是如何进行数据劫持的?说白了就是通过Object.defineProperty()来劫持对象属性的setter和ge ...

  10. OpenHarmony SystemUI开发记录

    背景介绍 最近学习OpenHarmony应用开发, SDK版本是3.2.9.2 Beta4,IDE版本是3.1.0.200.参考官方文档,做了个Demo应用,调试.运行非常顺利.启动应用后,状态栏和导 ...