dfs:深度优先搜索
- 岛屿的个数
中文English
给一个 01 矩阵,求不同的岛屿的个数。
0 代表海,1 代表岛,如果两个 1 相邻,那么这两个 1 属于同一个岛。我们只考虑上下左右为相邻。
Example
样例 1:
输入:
[
[1,1,0,0,0],
[0,1,0,0,1],
[0,0,0,1,1],
[0,0,0,0,0],
[0,0,0,0,1]
]
输出:
3
样例 2:
输入:
[
[1,1]
]
输出:
1
# #深度优先搜索 + 访问数组 + 方向数组
class Solution:
def numIslands(self,grid):
if not grid:
return 0
m,n = len(grid),len(grid[0])
# print("m: ",m)
# print("n: ",n)
visited = set()
numberOfIsland = 0
dirs = [
(0,1), #right
(0,-1),#left
(1,0),#down
(-1,0)#up
]
for i in range(m):
for j in range(n):
#
if self.check(grid,i,j,visited):
self.dfs(grid,i,j,visited,dirs)
numberOfIsland += 1
return numberOfIsland
def dfs(self,grid,x,y,visited,dirs):
visited.add((x,y))
# print("visited: ",visited)
for dx, dy in dirs:
nx = x+dx
ny = y+dy
if self.check(grid,nx,ny,visited):
self.dfs(grid,nx,ny,visited,dirs)
def check(self,grid,x,y,visited):
m,n = len(grid),len(grid[0])
if x >= 0 and x <m and y >= 0 and y < n and grid[x][y] and (x,y) not in visited:
return True
return False
if __name__ == '__main__':
a = Solution()
b = [
[1,1,0,0,0],
[0,1,0,0,1],
[0,0,0,1,1],
[0,0,0,0,1]
]
print(a.numIslands(b))
431—找无向图的连通块
描述
找出无向图中所有的连通块。
图中的每个节点包含一个label属性和一个邻接点的列表。(一个无向图的连通块是一个子图,其中任意两个顶点通过路径相连,且不与整个图中的其它顶点相连。)
注意事项
每个连通块内部应该按照label属性排序
说明
Learn more about representation of graphs
样例
给定图:
A------B C
\ | |
\ | |
\ | |
\ | |
D E
返回 {A,B,D}, {C,E}。其中有 2 个连通块,即{A,B,D}, {C,E}
注意事项
每个连通块内部应该按照label属性排序
class UndirectedGraphNode:
def __init__(self,x):
self.label = x
self.neighbors = []
from collections import defaultdict
class Solution:
def connectedSet(self,nodes):
if not nodes:
return []
components = []
visited = set()
for node in nodes:
if node.label not in visited:
self.findComponent(node,[],components,True,visited)
return components
def findComponent(self,node,component,components,isAddToComponents,visited):
component.append(node.label)
visited.add(node.label)
for nei in node.neighbors:
if nei.label not in visited:
self.findComponent(nei,component,components,False,visited)
if isAddToComponents:
component.sort()
print(component)
components.append(component)
if __name__ =='__main__':
node1= UndirectedGraphNode(1)
node2 = UndirectedGraphNode(2)
node3 = UndirectedGraphNode(3)
node4= UndirectedGraphNode(4)
node5= UndirectedGraphNode(5)
node1.neighbors = [node2,node4]
node2.neighbors = [node1,node4]
node3.neighbors = [node5]
node4.neighbors = [node1,node2]
node5.neighbors = [node3]
A = Solution()
nodes = [node1,node2,node3,node4,node5]
print(A.connectedSet(nodes))
- 数字组合
中文English
给定一个候选数字的集合 candidates 和一个目标值 target. 找到 candidates 中所有的和为 target 的组合.
在同一个组合中, candidates 中的某个数字不限次数地出现.
Example
样例 1:
输入: candidates = [2, 3, 6, 7], target = 7
输出: [[7], [2, 2, 3]]
样例 2:
输入: candidates = [1], target = 3
输出: [[1, 1, 1]]
Notice
所有数值 (包括 target ) 都是正整数.
返回的每一个组合内的数字必须是非降序的.
返回的所有组合之间可以是任意顺序.
解集不能包含重复的组合.
class Solution:
def combinationSum(self,candidates,target):
if not candidates:
return []
candidates.sort()
result = []
self.dfs(candidates,0,target,[],result)
return result
def dfs(self,candidates, startIndex, target, localCombos, result):
if target == 0:
result.append(localCombos[:]) #克隆
return
for i in range(startIndex,len(candidates)):
#去重
if i > startIndex and candidates[i] == candidates[i - 1]:
continue
if candidates[i] > target:
return
localCombos.append(candidates[i])
self.dfs(candidates,i,target-candidates[i],localCombos,result)
localCombos.pop()
if __name__ == '__main__':
a = Solution()
tar = 7
candid = [2,3,6,7]
print(a.combinationSum(candid, tar))
- 分割回文串
中文English
给定字符串 s, 需要将它分割成一些子串, 使得每个子串都是回文串.
返回所有可能的分割方案.
Example
样例 1:
输入: “a”
输出: [[“a”]]
解释: 字符串里只有一个字符, 也就只有一种分割方式 (就是它本身)
样例 2:
输入: “aab”
输出: [[“aa”, “b”], [“a”, “a”, “b”]]
解释: 有两种分割的方式.
1. 将 “aab” 分割成 “aa” 和 “b”, 它们都是回文的.
2. 将 “aab” 分割成 “a”, “a” 和 “b”, 它们全都是回文的.
Notice
不同的方案之间的顺序可以是任意的.
一种分割方案中的每个子串都必须是 s 中连续的一段.
class Solution:
#2019/08/28
#算法思想:
#-定义全局结果变量,self.res
#-对给定的字符串进行深度优先搜索,找出所有可行解,将其放入到全局结果集中
#-dfs每一个局部可行解使用局部变量保存,满足条件后加入到全局结果集
def partition(self,s):
if not s:
return []
result = []
self.dfs(s,[],result)
return result
#dfs函数职能:
# 对于给定的String,对其所有切分位置进行尝试,将所有可能的回文切分结果放入到
# localpartion中,并且将满足条件的
# LOCALPARTTION加入到全局集resultz中。
def dfs(self,string,localPartition,result):
if len(string) == 0:
result.append(localPartition[:])
return
for i in range(1,len(string)+1):
print("string[:i]: ", string[:i])
if self.isPalindrome(string[:i]):
# print(string[:i])
localPartition.append(string[:i])
print(localPartition)
self.dfs(string[i:],localPartition,result)
localPartition.pop()
def isPalindrome(self,string):
if not string:
return True
left,right = 0,len(string)-1
while left < right:
if string[left] != string[right]:
return False
left += 1
right -= 1
return True
if __name__ =='__main__':
a = Solution()
b = "aab"
print(a.partition(b))
153—数字组合
描述:
给出一组候选数字©和目标数字(T),找出C中所有的组合,使组合中数字的和为T。C中每个数字在每个组合中只能使用一次。
样例:
给出一个例子,候选数字集合为[10,1,6,7,2,1,5] 和目标数字 8 ,
解集为:[[1,7],[1,2,5],[2,6],[1,1,6]]
注意事项
所有的数字(包括目标数字)均为正整数。
元素组合(a1, a2, … , ak)必须是非降序(ie, a1 ≤ a2 ≤ … ≤ ak)。
解集不能包含重复的组合。
- 数字组合 II
中文English
给定一个数组 num 和一个整数 target. 找到 num 中所有的数字之和为 target 的组合.
Example
样例 1:
输入: num = [7,1,2,5,1,6,10], target = 8
输出: [[1,1,6],[1,2,5],[1,7],[2,6]]
样例 2:
输入: num = [1,1,1], target = 2
输出: [[1,1]]
解释: 解集不能包含重复的组合
Notice
在同一个组合中, num 中的每一个数字仅能被使用一次.
所有数值 (包括 target ) 都是正整数.
返回的每一个组合内的数字必须是非降序的.
返回的所有组合之间可以是任意顺序.
解集不能包含重复的组合.
- 子集 II
中文English
给定一个可能具有重复数字的列表,返回其所有可能的子集。
Example
样例 1:
输入:[0]
输出:
[
[],
[0]
]
样例 2:
输入:[1,2,2]
输出:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
Challenge
你可以同时用递归与非递归的方式解决么?
Notice
子集中的每个元素都是非降序的
两个子集间的顺序是无关紧要的
解集中不能包含重复子集
- 全排列
中文English
给定一个数字列表,返回其所有可能的排列。
Example
样例 1:
输入:[1]
输出:
[
[1]
]
样例 2:
输入:[1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
Challenge
使用递归和非递归分别解决。
Notice
你可以假设没有重复数字。
- 带重复元素的排列
中文English
给出一个具有重复数字的列表,找出列表所有不同的排列。
Example
样例 1:
输入:[1,1]
输出:
[
[1,1]
]
样例 2:
输入:[1,2,2]
输出:
[
[1,2,2],
[2,1,2],
[2,2,1]
]
Challenge
使用递归和非递归分别完成该题。
- 单词拆分 I
中文English
给定字符串 s 和单词字典 dict,确定 s 是否可以分成一个或多个以空格分隔的子串,并且这些子串都在字典中存在。
Example
样例 1:
输入: “lintcode”, [“lint”, “code”]
输出: true
样例 2:
输入: “a”, [“a”]
输出: true
- 单词拆分II
中文English
给一字串s和单词的字典dict,在字串中增加空格来构建一个句子,并且所有单词都来自字典。
返回所有有可能的句子。
Example
样例 1:
输入:“lintcode”,[“de”,“ding”,“co”,“code”,“lint”]
输出:[“lint code”, “lint co de”]
解释:
插入一个空格是"lint code",插入两个空格是 “lint co de”
样例 2:
输入:“a”,[]
输出:[]
解释:字典为空
- 上一个排列
中文English
给定一个整数数组来表示排列,找出其上一个排列。
Example
例1:
输入:[1]
输出:[1]
例2:
输入:[1,3,2,3]
输出:[1,2,3,3]
例3:
输入:[1,2,3,4]
输出:[4,3,2,1]
Notice
排列中可能包含重复的整数
- 下一个排列
中文English
给定一个整数数组来表示排列,找出其之后的一个排列。
Example
例1:
输入:[1]
输出:[1]
例2:
输入:[1,3,2,3]
输出:[1,3,3,2]
例3:
输入:[4,3,2,1]
输出:[1,2,3,4]
Notice
排列中可能包含重复的整数
10—字符串的不同排列
描述
给出一个字符串,找到它的所有排列,注意同一个字符串不要打印两次
样例
给出 “abb”,返回 [“abb”, “bab”, “bba”]。
给出 “aabb”,返回 [“aabb”, “abab”, “baba”, “bbaa”, “abba”, “baab”]