递归是指在函数内部调用自身本身的方法。能采用递归描述的算法通常有这样的特征:为求解规模为N的问题,设法将它分解成规模较小的问题,然后从这些小问题的解方便地构造出大问题的解,并且这些规模较小的问题也能采用同样的分解和综合方法,分解成规模更小的问题,并从这些更小问题的解构造出规模较大问题的解。特别地,当规模N=1时,能直接得解。
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
Given a set of distinct integers, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,3], a solution is:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
初始化,[ ]的子集为[ [ ] ]
nums[ : n]的子集为所有nums[ : n-1]的子集 加上所有nums[ : n-1]的子集+元素nums[n-1]
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
size = len(nums)
return self.solve(nums, size)
def solve(self, nums, n):
if n == 0:
return [[]]
temp = self.solve(nums[:n-1], n-1)
ans = temp[:]
for i in temp:
ans.append(i + [nums[n-1]])
return ans
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
For example,
If nums = [1,2,2], a solution is:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
在上一题思路的基础上,当nums[i]=nums[i-1]时,添加子集时只需在上一步增加的子集基础上进行添加nums[i],而不需要对所有子集进行添加nums[i]。故在递归返回结果时,返回两个结果,一个是所有子集,还有一个是该步骤中添加的子集的集合。
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort()
size = len(nums)
return self.solve(nums, size)[0]
def solve(self, nums, n):
if n == 0:
return [[]],[[]]
if n == 1:
return [[],[nums[n-1]]],[[nums[n-1]]]
temp = self.solve(nums[:n-1], n-1)
ans = temp[0][:]
l = len(ans)
if nums[n-1] == nums[n-2]:
for i in temp[1]:
ans.append(i + [nums[n-1]])
else:
for i in temp[0]:
ans.append(i + [nums[n-1]])
return ans,ans[l:]
LeetCode 39 Combination Sum
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
The same repeated number may be chosen from C unlimited number of times.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [2, 3, 6, 7] and target 7,
A solution set is:
[
[7],
[2, 2, 3]
]
LeetCode 40 Combination Sum II
Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C may only be used once in the combination.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates.sort()
self.ans = []
self.solve(candidates, target, 0 ,[])
return self.ans
def solve(self, candidates, target, start, path):
if target == 0:
self.ans.append(path)
return
if target < 0:
return
size = len(candidates)
for i in range(start, size):
if candidates[i] > target:
return
self.solve(candidates, target - candidates[i], i, path + [candidates[i]])
class Solution(object):
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates.sort()
self.ans = []
self.solve(candidates, target, 0, [])
return self.ans
def solve(self, candidates, target, start, path):
if target == 0:
self.ans.append(path)
return
if target < 0:
return
size = len(candidates)
for i in range(start, size):
if i != start and candidates[i] == candidates[i-1]:
continue
self.solve(candidates, target - candidates[i], i + 1, path + [candidates[i]])
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
在任意位置,左括号的个数要大于等于右括号的个数,如果左括号的个数有剩余,则+’(‘,递归,如果右括号有剩余,且小于左括号的的个数,则 +‘)‘,最后左右括号都不剩则排列结束。
class Solution(object):
def generateParenthesis(self, n):
"""
:type n: int
:rtype: List[str]
"""
self.res = []
self.generateParenthesisIter('',n, n)
return self.res
def generateParenthesisIter(self, mstr, r, l):
if r == 0 and l ==0:
self.res.append(mstr)
if l > 0:
self.generateParenthesisIter(mstr+'(', r, l-1)
if r > 0 and r > l:
self.generateParenthesisIter(mstr+')', r-1, l)
LeetCode 51 N-Queens
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other.
Given an integer n, return all distinct solutions to the n-queens puzzle.
Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space respectively.
For example,
There exist two distinct solutions to the 4-queens puzzle:
[
[“.Q..”, // Solution 1
“…Q”,
“Q…”,
“..Q.”],
[“..Q.”, // Solution 2
“Q…”,
“…Q”,
“.Q..”]
]
class Solution(object):
def solveNQueens(self, n):
"""
:type n: int
:rtype: List[List[str]]
"""
self.ans = []
self.board = [-1 for i in range(n)]
self.dfs(0, [], n)
return self.ans
def isQueen(self, krow, jcolumn):
for i in range(krow):
if self.board[i] == jcolumn or abs(krow-i) == abs(self.board[i] - jcolumn):
return False
return True
def dfs(self, krow, rowlist, n):
if krow == n:
self.ans.append(rowlist)
for i in range(n):
if self.isQueen(krow,i):
self.board[krow] = i
self.dfs(krow + 1,rowlist + ['.' * i + 'Q' + '.' * (n-i-1)],n)
class Solution(object):
def totalNQueens(self, n):
"""
:type n: int
:rtype: int
"""
self.ans = []
self.board = [-1 for i in range(n)]
self.dfs(0, [], n)
return len(self.ans)
def isQueen(self, krow, jcolumn):
for i in range(krow):
if self.board[i] == jcolumn or abs(krow-i) == abs(self.board[i] - jcolumn):
return False
return True
def dfs(self, krow, rowlist, n):
if krow == n:
self.ans.append(rowlist)
for i in range(n):
if self.isQueen(krow,i):
self.board[krow] = i
self.dfs(krow + 1,rowlist + ['.' * i + 'Q' + '.' * (n-i-1)],n)
Remember the story of Little Match Girl? By now, you know exactly what matchsticks the little match girl has, please find out a way you can make one square by using up all those matchsticks. You should not break any stick, but you can link them up, and each matchstick must be used exactly one time.
Your input will be several matchsticks the girl has, represented with their stick length. Your output will either be true or false, to represent whether you could make one square using all the matchsticks the little match girl has.
Example 1:
Input: [1,1,2,2,2]
Output: true
Explanation: You can form a square with length 2, one side of the square came two sticks with length 1.
Example 2:
Input: [3,3,3,3,4]
Output: false
Explanation: You cannot find a way to form a square with all the matchsticks.
根据火柴棒的总长度,求正方形的变长,若变长不为整数,则直接判断为False。
先将nums按从大到小的顺序排序,used为和nums等长的列表,用于记录第i位的元素是否被用过。
使用递归判断从第i位元素起始,能否找到这样的组合满足其长度之和等于正方形的边长。
(1)若满足初始条件,则返回结果(True or False)
(2)若不满足条件,则进行递归,在剩下的元素中进行选择,看有没有满足情况的,如果没有满足情况的,used对应位置改为False,结果返回False
(3)对nums中的每个元素进行遍历,看能否满足nums中的每个火柴棒都能找到对应边的组合,其长度和等于正方形边长。
class Solution(object):
def makesquare(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
total = sum(nums)
if total%4 != 0 or len(nums)<4: return False
size = total/4
nums.sort(reverse=True)
used = [False]*len(nums)
def dfs(i, expect):
if i >= len(nums): return expect%size == 0
if used[i]: return dfs(i+1, expect)
used[i] = True
if nums[i] == expect: return True
if nums[i] < expect:
expect -= nums[i]
available = [j for j in range(i+1, len(nums)) if not used[j]]
for x in available:
if dfs(x, expect):
return True
used[i] = False
return False
for i in range(len(nums)):
if not dfs(i, size): return False
return True