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编写。代码如下:

  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. func main() {
  7. ret := jump2([][]int{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}})
  8. fmt.Println(ret)
  9. }
  10. func getMin(a, b int) int {
  11. if a < b {
  12. return a
  13. } else {
  14. return b
  15. }
  16. }
  17. // 优化方法, 利用线段树做枚举优化
  18. // 因为线段树,下标从1开始
  19. // 所以,该方法中所有的下标,请都从1开始,防止乱!
  20. func jump2(arr [][]int) int {
  21. n := len(arr)
  22. m := len(arr[0])
  23. map0 := make([][]int, n+1)
  24. for i := 0; i < n+1; i++ {
  25. map0[i] = make([]int, m+1)
  26. }
  27. for a, b := 0, 1; a < n; a, b = a+1, b+1 {
  28. for c, d := 0, 1; c < m; c, d = c+1, d+1 {
  29. map0[b][d] = arr[a][c]
  30. }
  31. }
  32. rowTrees := make([]*SegmentTree, n+1)
  33. for i := 1; i <= n; i++ {
  34. rowTrees[i] = NewSegmentTree(m)
  35. }
  36. colTrees := make([]*SegmentTree, m+1)
  37. for i := 1; i <= m; i++ {
  38. colTrees[i] = NewSegmentTree(n)
  39. }
  40. rowTrees[n].update0(m, m, 0, 1, m, 1)
  41. colTrees[m].update0(n, n, 0, 1, n, 1)
  42. for col := m - 1; col >= 1; col-- {
  43. if map0[n][col] != 0 {
  44. left := col + 1
  45. right := getMin(col+map0[n][col], m)
  46. next := rowTrees[n].query(left, right, 1, m, 1)
  47. if next != math.MaxInt64 {
  48. rowTrees[n].update0(col, col, next+1, 1, m, 1)
  49. colTrees[col].update0(n, n, next+1, 1, n, 1)
  50. }
  51. }
  52. }
  53. for row := n - 1; row >= 1; row-- {
  54. if map0[row][m] != 0 {
  55. up := row + 1
  56. down := getMin(row+map0[row][m], n)
  57. next := colTrees[m].query(up, down, 1, n, 1)
  58. if next != math.MaxInt64 {
  59. rowTrees[row].update0(m, m, next+1, 1, m, 1)
  60. colTrees[m].update0(row, row, next+1, 1, n, 1)
  61. }
  62. }
  63. }
  64. for row := n - 1; row >= 1; row-- {
  65. for col := m - 1; col >= 1; col-- {
  66. if map0[row][col] != 0 {
  67. // (row,col) 往右是什么范围呢?[left,right]
  68. left := col + 1
  69. right := getMin(col+map0[row][col], m)
  70. next1 := rowTrees[row].query(left, right, 1, m, 1)
  71. // (row,col) 往下是什么范围呢?[up,down]
  72. up := row + 1
  73. down := getMin(row+map0[row][col], n)
  74. next2 := colTrees[col].query(up, down, 1, n, 1)
  75. next := getMin(next1, next2)
  76. if next != math.MaxInt64 {
  77. rowTrees[row].update0(col, col, next+1, 1, m, 1)
  78. colTrees[col].update0(row, row, next+1, 1, n, 1)
  79. }
  80. }
  81. }
  82. }
  83. return rowTrees[1].query(1, 1, 1, m, 1)
  84. }
  85. // 区间查询最小值的线段树
  86. // 注意下标从1开始,不从0开始
  87. // 比如你传入size = 8
  88. // 则位置对应为1~8,而不是0~7
  89. type SegmentTree struct {
  90. min []int
  91. change []int
  92. update []bool
  93. }
  94. func NewSegmentTree(size int) *SegmentTree {
  95. ret := &SegmentTree{}
  96. N := size + 1
  97. ret.min = make([]int, N<<2)
  98. ret.change = make([]int, N<<2)
  99. ret.update = make([]bool, N<<2)
  100. ret.update0(1, size, math.MaxInt64, 1, size, 1)
  101. return ret
  102. }
  103. func (this *SegmentTree) pushUp(rt int) {
  104. this.min[rt] = getMin(this.min[rt<<1], this.min[rt<<1|1])
  105. }
  106. func (this *SegmentTree) pushDown(rt, ln, rn int) {
  107. if this.update[rt] {
  108. this.update[rt<<1] = true
  109. this.update[rt<<1|1] = true
  110. this.change[rt<<1] = this.change[rt]
  111. this.change[rt<<1|1] = this.change[rt]
  112. this.min[rt<<1] = this.change[rt]
  113. this.min[rt<<1|1] = this.change[rt]
  114. this.update[rt] = false
  115. }
  116. }
  117. // 最后三个参数是固定的, 每次传入相同的值即可:
  118. // l = 1(固定)
  119. // r = size(你设置的线段树大小)
  120. // rt = 1(固定)
  121. func (this *SegmentTree) update0(L, R, C, l, r, rt int) {
  122. if L <= l && r <= R {
  123. this.update[rt] = true
  124. this.change[rt] = C
  125. this.min[rt] = C
  126. return
  127. }
  128. mid := (l + r) >> 1
  129. this.pushDown(rt, mid-l+1, r-mid)
  130. if L <= mid {
  131. this.update0(L, R, C, l, mid, rt<<1)
  132. }
  133. if R > mid {
  134. this.update0(L, R, C, mid+1, r, rt<<1|1)
  135. }
  136. this.pushUp(rt)
  137. }
  138. // 最后三个参数是固定的, 每次传入相同的值即可:
  139. // l = 1(固定)
  140. // r = size(你设置的线段树大小)
  141. // rt = 1(固定)
  142. func (this *SegmentTree) query(L, R, l, r, rt int) int {
  143. if L <= l && r <= R {
  144. return this.min[rt]
  145. }
  146. mid := (l + r) >> 1
  147. this.pushDown(rt, mid-l+1, r-mid)
  148. left := math.MaxInt64
  149. right := math.MaxInt64
  150. if L <= mid {
  151. left = this.query(L, R, l, mid, rt<<1)
  152. }
  153. if R > mid {
  154. right = this.query(L, R, mid+1, r, rt<<1|1)
  155. }
  156. return getMin(left, right)
  157. }

执行结果如下:


左神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. [jointjs] 自定义shape

    前面一篇写了使用jointjs实现自动布局和拖拽缩放,这篇记录一下自定义图形. 首先jointjs内置的图形有很多,文档已经列出来了: 但是有时候这些图形满足不了我们的需求,就需要我们自己去绘制自己想 ...

  2. jdk8 stream部分排序方法

    List<类> list; 代表某集合   //返回 对象集合以类属性一升序排序   list.stream().sorted(Comparator.comparing(类::属性一)); ...

  3. Android 音视频 - EGL 源码解析以及 C++ 实现

    OpenGL 是一个跨平台的 API,而不同的操作系统(Windows,Android,IOS)各有自己的屏幕渲染实现.所以 OpenGL 定义了一个中间接口层 EGL(Embedded Graphi ...

  4. [C++/Java/Py/C#/Ruby/Swift/Go/Scala/Kotlin/Rust/PHP/TS/Elixir/Dart/Racket/Erlang] LeetCode2185. 统计包含给定前缀的字符串

    目录 题解地址 代码 cpp java python3 C# ruby swift golang scala kotlin rust php typescript elixir dart racket ...

  5. 基于深度学习的车型识别系统(Python+清新界面+数据集)

    摘要:基于深度学习的车型识别系统用于识别不同类型的车辆,应用YOLO V5算法根据不同尺寸大小区分和检测车辆,并统计各类型数量以辅助智能交通管理.本文详细介绍车型识别系统,在介绍算法原理的同时,给出P ...

  6. 第一次博客:PTA题目集1-3总结

    第一次博客:PTA题目集1-3总结 前言:JAVA是一门非常好的语言,因其面向对象的思想,在解决问题时思路与上学期学习的C语言截然不同,但是其优势也是显然易见的,特别是在写大型程序时其面向对象的思想, ...

  7. 超详细!手把手教你用 JaCoCo 生成单测覆盖率报告!

    我们都知道 Spock 是一个单测框架,其特点是语法简明.但当我们使用 Spock 写了一堆单元测试之后,如何生成对应的单测覆盖率报告呢?一般来说,我们会使用两个插件来一起完成单测覆盖率报告的生成,分 ...

  8. IPv4已正式用尽

    网际协议版本4 (英语:Internet Protocol version 4,缩写:IPv4,又称互联网通信协议第四版)是网际协议开发过程中的第四个修订版本,也是此协议第一个被广泛部署和使用的版本. ...

  9. python入门教程之十五获取对象属性的几种方法

    当我们拿到一个对象的引用时,如何知道这个对象是什么类型.有哪些方法呢? 使用type() 首先,我们来判断对象类型,使用type()函数: 基本类型都可以用type()判断: >>> ...

  10. 部署:mysql搭建多主一从源复制环境

    问题描述:搭建过一主多从的环境,由于数据库数据一致性要求高,有些情景会搭建一主多从的架构,搭建多主一从的模式,相对来说适合数据整合,将多个业务的库整合到一起,方便做查询,也可以当做一个监控其他主库数据 ...