leetcode51-55

1. N皇后(Hard)

nは研究クイーン問題はどのようにあるn個置かクイーンズのn × nはボード上の、そして女王はお互いにお互いを攻撃することはできません。

画像ショー8つのクイーンの問題を解決するためのAの方法。

整数所与N、すべての異なる返し、n個の女王の問題に対する解決策を。

各溶液は、明示的な含有Nクイーン問題片は、プログラムの実施例を配置'Q'し、'.'スペース、クイーンを表します。

例:

1 
2
3
4
5
6
7
8
9
10
11
12
13
入力:4 
出力:[
[ ".Q .. " //ソリューション1
" ... Q"、
"Q ..."、
"..Q"]、

[ "..Q。 " //ソリューション2
"Q ..."、
" ... Q"、
".Q .."]
]
説明:4つのクイーン問題の二つの異なる解決策があります。

回答:

アイデア:バックトラック

この質問は困難であり、新入生はとても難しいと感じました。

アルゴリズムの設立に先立ち、私たちは2つの有用な詳細を検討してみましょう。

  1. ラインだけの女王を持ってもよく、1つだけの女王を有することができます。

  2. これは、ボード上の正方形のすべてを考慮する必要がないことを意味します。単純に列を循環さ押します。

  3. 列番号=定数 - がすべての主要な対角線のための+定数行番号=列番号は、全ての行番号は、対角線のビューを持っています。

  4. これは、私たちは、攻撃範囲の対角マークを持ち、攻撃位置にいるかどうかボックス(行番号、列番号)を確認することを可能にします。

今、あなたは、関数、バックトラック(行= 0)を書き戻すことができます。

  • 開始= 0から最初の行。

  • サイクルと女王の各列に列を配置しようとする試み。

    • グリッド(行、列)は、攻撃の範囲内にない場合
      • (行、列)でグリッドクイーン上に配置されます。
      • 行、列、対角線に対応する負の位置。
      • すべての行が考慮される場合、行== N
        • 我々は解決策を見つけた手段
      • エルス
        • 女王は次の場所のバックトラック(行+ 1)を考慮し続けています。
      • バック:(行、列)の二乗クイーンで除去されます。
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
クラス (オブジェクト)DEF solveNQueens (自己、N) "" " タイプN:INT         :RTYPE:リスト[リスト[STR]         """ DEF could_place (行、列)復帰しない(COLS [COL] +丘[行- COL] +デール[行+ COL]) DEF place_queen (行、列)             queens.add((行、列))            COLS [COL = 1つの             丘[行- COL = 1             デール[行+ COL = 1 DEF remove_queen (行、列)             queens.remove((行、列))














COLS [COL] = 0
-丘[行COL = 0
デール[行+ COL = 0 DEF add_solution () 溶液= [] のため _、COL :ソート(クイーン) solution.append('' * COL + 'Q' + '' *(N-COL -1)) output.append(溶液)DEF バックトラック(行= 0のために COL における範囲(N):もし could_place(行、列): place_queen(行、 COL)









もし行+ 1 == N:
add_solution() バックトラック(行+ 1 remove_queen(行、列) COLS = [ 0 ] * N 丘= [ 0 ] *(2 * N -1 デール= [ 0 ] *(2 * N -1 クイーン=セット() 出力= [] バックトラック()戻り値の出力










思考2​​:DFS

エイトクイーン問題は、より一般的な場所に拡張n個の問題をQUEENSすることができます。この時、ボードの大きさはN×Nとなり、女王は、n数となっています。場合にのみ、N = 1又はN≥4ときに問題解ける場合。

对于任意(x,y),如果要让新的点和它不能处于同一条横行、纵行或斜线上,则新点(p,q)必须要满足p+q != x+y 和p-q!= x-y, 前者针对左下右上斜线,后者针对左上右下斜线,两者同时都保证了不在同一条横行和纵行上。

代码中变量的含义:

  • cols_lst: 每一行皇后的column位置组成的列表
  • cur_row:目前正在判断的row的index
  • xy_diff:所有x-y组成的列表
  • xy_sum:所有x+y组成的列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class (object):
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
def dfs(cols_lst, xy_diff, xy_sum):
cur_row = len(cols_lst)
if cur_row == n:
ress.append(cols_lst)
for col in range(n):
if col not in cols_lst and cur_row - col not in xy_diff and cur_row + col not in xy_sum:
dfs(cols_lst+[col], xy_diff+[cur_row-col], xy_sum+[cur_row+col])
ress = []
dfs([], [], [])
return [['.' * i + 'Q' + '.' * (n-i-1) for i in res] for res in ress]

2. N皇后2(Hard)

n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回 n 皇后不同的解决方案的数量。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
输入: 4
输出: 2
解释: 4 皇后问题存在如下两个不同的解法。
[
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],

["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]

解答:

思路:

和上题完全一模一样,只是最后输出的时候,输出的是结果的长度。

1
2
3
4
5
大专栏  leetcode51-556
7
8
9
10
11
12
13
14
15
16
class (object):
def totalNQueens(self, n):
"""
:type n: int
:rtype: int
"""
def dfs(col_list,xy_diff,xy_sum):
cur_row = len(col_list)
if cur_row == n:
ress.append(col_list)
for col in range(n):
if col not in col_list and cur_row-col not in xy_diff and cur_row+col not in xy_sum:
dfs(col_list+[col],xy_diff+[cur_row-col],xy_sum+[cur_row+col])
ress = []
dfs([],[],[])
return len(ress)

3. 最大子序和(Easy)

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

1
2
3
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

进阶:

如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。

解答:

思路:

这道题很简单,动态规划,逐步更新局部最优解和全局最优解。

1
2
3
4
5
6
7
8
9
10
11
class (object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
cur_sum,all_sum = nums[0],nums[0]
for i in range(1,len(nums)):
cur_sum = max(cur_sum+nums[i],nums[i])
all_sum = max(all_sum,cur_sum)
return all_sum

4. 螺旋矩阵(Medium)

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

1
2
3
4
5
6
7
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,3,6,9,8,7,4,5]

示例 2:

1
2
3
4
5
6
7
输入:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

解答:

思路:

绘制螺旋轨迹路径,我们发现当路径超出界限或者进入之前访问过的单元格时,会顺时针旋转方向。

算法

假设数组有R 行 C 列,seen[r][c]表示第 r 行第 c 列的单元格之前已经被访问过了。当前所在位置为 (r, c),前进方向是 di。我们希望访问所有 R x C 个单元格。

当我们遍历整个矩阵,下一步候选移动位置是(next_r, next_c)。如果这个候选位置在矩阵范围内并且没有被访问过,那么它将会变成下一步移动的位置;否则,我们将前进方向顺时针旋转之后再计算下一步的移动位置。

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
class (object):
def spiralOrder(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: List[int]
"""
if not matrix:
return []
R = len(matrix)
C = len(matrix[0])
seen = [[False]*C for _ in matrix]
dr = [0,1,0,-1]
dc = [1,0,-1,0]
r = c = di = 0
ans = []
for _ in range(R*C):
ans.append(matrix[r][c])
seen[r][c] = True
next_r,next_c = r+dr[di],c+dc[di]
if 0<= next_r < R and 0<= next_c < C and not seen[next_r][next_c]:
r = next_r
c = next_c
else:
di = (di+1)%4
r = r + dr[di]
c = c + dc[di]
return ans

5. 跳跃游戏(Medium)

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个位置。

示例 1:

1
2
3
输入: [2,3,1,1,4]
输出: true
解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置。

示例 2:

1
2
3
输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。

解答:

思路:

这个题很好想。

就是从后往前倒推,如果倒数第二个能到底倒数第一个位置,那么可以就去求是否可以达到倒数第二个位置。

就是反复往回推的过程。

1
2
3
4
5
6
7
8
9
10
11
クラス のソリューション(オブジェクト)デフcanJump (自己、NUMS) "" " タイプNUMS:リスト[INT]         :RTYPE:BOOL         """         (NUMS)lenの最後= -1 のために、私は範囲(LEN(NUMS) - 1 -1 -1):もし I + NUMS [I]> =最後:                私が最後=戻り最後== 0










おすすめ

転載: www.cnblogs.com/liuzhongrong/p/11873953.html