- 921. Minimum Add to Make Parentheses Valid 使括号有效的最少添加
- 915. Partition Array into Disjoint Intervals 分割数组
- 932. Beautiful Array 漂亮数组
- 940. Distinct Subsequences II 不同的子序列 II
题目地址:https://leetcode.com/problems/knight-dialer/description/
Achess knight can move as indicated in the chess diagram below:
.
This time, we place our chess knight on any numbered key of a phone pad (indicated above), and the knight makes N-1
hops. Each hop must be from one key to another numbered key.
Each time it lands on a key (including the initial placement of the knight), it presses the number of that key, pressing N
digits total.
Howmany distinct numbers can you dial in this manner?
Since the answer may be large, output the answer modulo 10^9 + 7.
Example 1:
Input: 1
Output: 10
Example 2:
Input: 2
Output: 20
Example 3:
Input: 3
Output: 46
Note:
1、 1<=N<=5000;
马的初始位置可以在拨号按键的任意位置,现在要让它走N - 1步,问这个马能产生出多少种不同的拨号号码?
本周周赛第二题,卡了我好久啊!好气!
这个题本身肯定是动态规划题目,设置dp数组为当前步以每个按键结尾的状态数。所以我使用了一个4×3的二维数组,需要注意的是左下角和右下角的位置不可能到达,设置它的数值为0.状态转移方程很好求得,那就是把上一步可能存在的位置状态累加在一起就成了当前位置的状态数。
问题是会超时啊!甚至可能会超过内存限制!
先上一份很容易想到的,但是会超时TLE的代码:
时间复杂度是O(N),空间复杂度O(N).
class Solution:
def knightDialer(self, N):
"""
:type N: int
:rtype: int
"""
self.ans = dict()
self.ans[0] = 10
board = [[1] * 3 for _ in range(4)]
board[3][0] = board[3][3] = 0
pre_dict = {(i, j) : self.prevMove(i, j) for i in range(4) for j in range(3)}
for n in range(1, N):
new_board = copy.deepcopy(board)
for i in range(4):
for j in range(3):
cur_move = 0
for x, y in pre_dict[(i, j)]:
cur_move = (cur_move + board[x][y]) % (10 ** 9 + 7)
new_board[i][j] = cur_move
board = new_board
return sum([board[i][j] for i in range(4) for j in range(3)]) % (10 ** 9 + 7)
def prevMove(self, i, j):
if (i, j) == (3, 0) or (i, j) == (3, 2):
return []
directions = [(-2, 1), (-1, 2), (1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1)]
res = []
for d in directions:
x, y = i + d[0], j + d[1]
if 0 <= x < 4 and 0 <= y < 3 and (x, y) != (3, 0) and (x, y) != (3, 2):
res.append((x, y))
return res
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
在比赛的时候剩下的一个小时都在优化这个题,个人感觉这个题卡时间卡的有点太严了,上面这个做法应该是标准做法吧,通过不了,需要一些奇技淫巧才能通过。
这是我在比赛最后的时间通过的代码,把所有状态给初始化了,这样好处是可以不用在循环中不停地copy原来的棋盘状态了,同时利用了对称性,只需要求出4个位置(1,2,4,0)的状态,其余状态可以直接利用对称性得到。
还有一个优化的地方在于在每次的过程中进行取模!虽然取模运算是耗时的运算,但是数字很大的时候,大整数既占空间又占时间,所以取模!
经过上面的优化勉强通过了,真是不容易,我觉得这个题非常不友好,因为同样的Java代码可以不做任何优化就通过了。这个题在N很大的时候还会告诉我内存超了……简直了。。
时间复杂度是O(N),空间复杂度O(N).总时间1500ms。
class Solution:
def knightDialer(self, N):
"""
:type N: int
:rtype: int
"""
self.ans = dict()
self.ans[0] = 10
board = [[[1] * 3 for _ in range(4)] for _ in range(N)]
board[0][3][0] = board[0][3][2] = 0
pre_dict = {(i, j) : self.prevMove(i, j) for i in range(4) for j in range(3)}
for n in range(1, N):
for i in range(2):
cur_move = 0
for x, y in pre_dict[(i, 0)]:
cur_move += board[n - 1][x][y]
board[n][i][0] = cur_move % (10 ** 9 + 7)
cur_move = 0
for x, y in pre_dict[(0, 1)]:
cur_move += board[n - 1][x][y]
board[n][0][1] = cur_move % (10 ** 9 + 7)
cur_move = 0
for x, y in pre_dict[(3, 1)]:
cur_move += board[n - 1][x][y]
board[n][3][1] = cur_move % (10 ** 9 + 7)
board[n][4][0] = board[n][0][0]
board[n][0][2] = board[n][0][0]
board[n][5][1] = 0
board[n][6][2] = board[n][7][0]
board[n][8][1] = board[n][0][1]
board[n][9][2] = board[n][0][2]
board[n][3][0] = board[n][3][2] = 0
return (board[N - 1][0][0] * 4 + board[N - 1][0][1] * 2 + board[N - 1][10][0] * 2 + board[N - 1][3][1] + board[N - 1][11][1]) % (10 ** 9 + 7)
def prevMove(self, i, j):
if (i, j) == (3, 0) or (i, j) == (3, 2):
return []
directions = [(-2, 1), (-1, 2), (1, 2), (2, 1), (2, -1), (1, -2), (-1, -2), (-2, -1)]
res = []
for d in directions:
x, y = i + d[0], j + d[1]
if 0 <= x < 4 and 0 <= y < 3 and (x, y) != (3, 0) and (x, y) != (3, 2):
res.append((x, y))
return res
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
上面的做法我一直在想着优化时间复杂度,事实上,每个状态只和之前的状态有关,所以很容易想到优化空间复杂度。
使用10个变量,分别保存每个位置能取到的状态数,然后人为的把每个状态能通过其他的状态得到的代码给写出来就行了。
代码如下,真的很简洁,为什么我没有想到优化空间!!优化之后时间降到了264 ms,这个告诉我们,优化空间同样可以大规模地降低时间,如果DP问题超时的话,优先考虑空间!
时间复杂度是O(N),空间复杂度O(1).时间264 ms.
class Solution:
def knightDialer(self, N):
"""
:type N: int
:rtype: int
"""
if N == 1: return 10
x1 = x2 = x3 = x4 = x5 = x6 = x7 = x8 = x9 = x0 = 1
MOD = 10 ** 9 + 7
for i in range(N - 1):
x1, x2, x3, x4, x5, x6, x7, x8, x9, x0 = (x6 + x8) % MOD,\
(x7 + x9) % MOD, (x4 + x8) % MOD, (x3 + x9 + x0) % MOD, 0, (x1 + x7 + x0) % MOD,\
(x2 + x6) % MOD, (x1 + x3) % MOD, (x2 + x4) % MOD, (x4 + x6) % MOD
return (x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x0) % MOD
1 2 3 4 5 6 7 8 9 10 11 12 13 14
如果在上面的解法上再利用好对称性的话,可以把时间再次降低到160 ms。
时间复杂度是O(N),空间复杂度O(1).时间160 ms。
class Solution:
def knightDialer(self, N):
"""
:type N: int
:rtype: int
"""
if N == 1: return 10
x1 = x2 = x3 = x4 = x5 = x6 = x7 = x8 = x9 = x0 = 1
MOD = 10 ** 9 + 7
for i in range(N - 1):
x1, x2, x4, x0 = (x6 + x8) % MOD, (x7 + x9) % MOD, (x3 + x9 + x0) % MOD, (x4 + x6) % MOD
x3, x5, x6, x7, x8, x9 = x1, 0, x4, x1, x2, x1
return (x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x0) % MOD
1 2 3 4 5 6 7 8 9 10 11 12 13
688. Knight Probability in Chessboardopen in new window
https://leetcode.com/problems/knight-dialer/discuss/189252/O(logN)
DDKK.COM 弟弟快看-教程,程序员编程资料站,版权归原作者所有
本文经作者:负雪明烛 授权发布,任何组织或个人未经作者授权不得转发
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
之前有人问过 Knight 的巡演,但我仍然遇到问题。我正在尝试递归访问棋盘的所有单元格,但我不能进行超过 52 次访问。之后它回溯并且访问的单元格的数量倒计时。这是我的代码: public clas
题目地址:https://leetcode.com/problems/knight-dialer/description/ 题目描述 Achess knight can move as indic
我正在尝试使用DFS制作程序骑士之旅,但我无法解决这个程序..因为我总是有这样的消息错误 线程“AWT-EventQueue-0”中的异常java.lang.ArrayIndexOutOfBounds
我正在尝试学习 USACO 算法培训类(class) (http://ace.delos.com/usacogate) - 我目前正在访问一个描述 DFS、BFS 等的页面。我理解这些概念,但是他们给
我编码 Knight's tour 算法在 C++ 中使用 Backtracking 方法。但对于 n > 7(大于 7 x 7 棋盘),它似乎太慢或陷入无限循环。 问题是: Time complex
我正在用java制作一个游戏。我想达到这样的效果: 我该怎么做?我不是要求代码,而是要求关键字,因为我真的不知道如何实现这一点。我应该只用 Sprite 做一个普通的动画吗?问题是结果不会很顺利。也许
我正在 Codeblocks IDE 中使用 C 语言编写以下代码,尝试使用递归和回溯来解决骑士之旅问题。但问题是它会永远持续下去并且不会给出任何输出,尽管我认为这不是无限递归的情况。 #includ
我正在使用基本 gui 解决骑士之旅问题,我想在两个文本字段中获取用户输入,这两个文本字段组成了用户的 (x,y),然后在一个文本框中打印,如果解决方案可行的话,并且在另一个中,我写了骑士采用的路径。
我正在尝试用 javascript 编写一个算法来使用回溯法解决 Knight's Tour 问题,但它不起作用。基本上,该函数应该输出一个名为 visited 的数组,其中包含每个移动的位置。但是,
我对 Knight's Tour 的递归回溯方法遇到了无限循环。起初,我认为这个问题通常可能会花费这么多时间,但有些解决方案可以立即解决。请告诉我的代码有什么问题。 package io.github
我正在尝试写一个 Knights Walk Algorithm (蛮力)使用 Java。我能够创建一个程序来移动 5x5 网格,但该程序总是将 06 个单元格遗漏在板上。我的骑士也无法从这些方 blo
我最近提取了一个 C 程序 ( https://repl.it/Klpv ),用于在 8 x 8 的棋盘上搜索骑士之旅。我用 JavaScript 重新编写了程序(因为我更了解 JS),然后我修改了程
尝试在 N*N 棋盘上修改骑士运动集的 N-Queens 算法。在我的例子中,我在 4*4 和 8*8 板上测试它。 我的算法,resp。我的递归无法处理骑士,因为它有时需要跳过一行。如果只是皇后移动
我目前正在使用 C++ 开发 Knight tour Chessboard 游戏,使用 Stack 来存储我的移动。我遇到了一个奇怪的循环,它没有结束程序。有人可以帮我处理代码吗? #include
我目前正在尝试使用 Warnsdorff 规则改进 Knight's Tour 的暴力执行,但是我觉得我好像不理解算法,因为脚本的执行需要很长时间。我主要是在寻找提示以指明正确的方向,以便我可以自己尽
class Knight { public static readonly double LegalDistance = Math.Sqrt(5); public Stack Step
我一直在做一个学校项目,但无法解决这个问题。出现死胡同时,骑士会跳回到最后一步的问题。 我已经添加了 4x4 测试的输出,您可以清楚地看到,当骑士看到 12 号有一条死路时,它会跳回到 11 号回合。
我正在尝试解决 Knight's Open Tour在 Haskell 中,并提出一个解决方案来生成所有可能的解决方案: knightsTour :: Int -> [[(Int, Int)]] kn
我正在尝试制作一个程序,它与一个骑士一起遍历棋盘的所有方格(大小并不重要,但现在是 6x6),称为“骑士之旅”check it out on wiki . 游览应该是关闭的,这意味着最后一次访问的方格
我是一名优秀的程序员,十分优秀!