#coding:utf-8
import scrapy
import xlwt, lxml
import re, json
import matplotlib.pyplot as plt
import numpy as np
import pylab
from scipy import linalg
from igraph import *
from collections import deque
#图论
'''
BFS(Breadth First Sreach)--广度优先搜索
最简单\直接的图搜索算法
从起点开始层层扩展
第一层是离起点为1的
第二层是离起点为2的
......
本质就是按层(距离)扩展,无回退
BFS分析的两个要点
结点判重:如果在扩展中发现某节点在前期已经访问过,则本次不再访问该节点;显然,第一次访问到该节点时,是访问次数最少的:最少,最短
路径记录:
一个结点可能扩展出多个结点:多后继 a1a2... ; 但是任意一个结点最多只可能有一个前驱(起始结点没有前驱):单前驱
用和结点数目等长的数组pre[0...N-1];
pre[i]=j:第i个结点的前驱是j
存索引,不存数据本身
BFS算法框架
辅助数据结构:队列q;结点是第几次被访问到的d[0...N-1],简称步数
算法描述:
起点start入队q
记录步数d[start]=0
记录start的前驱pre[start]=-1
如果队列q非空,则队首结点X出队,尝试扩展X
找到X的邻接点集合{y|(x,y)属于E}
对于每一个新扩展结点y判重,如果y是新结点,则入队q
同时,记录步数d[y]=d[x]+1;前驱pre[y]=x
'''
'''
单词变换问题 Word ladder
给定字典和一个起点单词,一个终点单词,每次只能变换一个字母,问从起点单词是否可以到达终点单词?最短多少步?
如,start='hit'
end='cog'
dict=['hot','dot','dog','lot','log']
hit->hot->dot->dog->cog
使用邻接表,建立单词间的联系
单词为图的结点,若能够变换则,两个单词存在无向边
-> 若单词A和B只有一个字母不同,则A-B存在边
建图:
预处理:
1.对字典中的所有单词建立map,hash或者trie结构,利于后序的查找
2.对于某单词w,单词中的第i位记为β,则将β替换为[β+1,z],查找新的串nw是否在字典中.如果在,将w-nw添加到邻接表项w和nw中(无向边)
3.循环处理第二步
//若使用map,串在字典中的查找认为是O(logN)的,那么,整体时间复杂度为O(N*len*13*logN),即O(N*logN);若使用hash或者trie,整体复杂度为O(N)
从起始单词开始,广度优先搜素,看能否达到终点单词.若可以,则这条路径上的变化是最快的
[虽然起点单词开始到终点单词的路径内的单词必须在字典内,但起点和终点本身没有要求]
'''
'''
#bfs
class Graph(object):
def __init__(self):
self.order=[]
self.neighbor={}
def add_node(self,node):
key,val=node#邻接表的形式存储图
if not isinstance(val,list):
print('node should be a list')
self.neighbor[key]=val
def broadth_first(self,root):
if root:
search_queue=deque()
search_queue.append(root)
visited=[]
else:
print('root is None')
return -1
while search_queue:
x=search_queue.pop(0)
if not x in visited and x in self.neighbor.keys():#判重以及检查是否属于图中结点
search_queue+=self.neighbor[x]
visited.append(x)
'''
def wordLadder(start,end,wordlist):
wordlist.append(start)
wordlist.append(end)
length=len(wordlist)
# glist=[]
glist2={}#每个结点可扩展的结点集合【邻接矩阵的形式】
for i in range(0,length):
w=wordlist[i]
temp=[]
for j in range(0,len(w)):
for k in range(ord('a'),ord('z')):
# for k in range(ord(w[j])+1,ord('z')):
nw=w.replace(w[j],chr(k),1)
if nw in wordlist and nw!=w:
# if nw in wordlist :
temp.append(nw)
# glist.append((w,nw))
glist2[w]=temp
print(glist2)
# print(glist)#有联系(能形成边,无向)的结点
# g=Graph.TupleList(glist,directed=False,vertex_name_attr='name')
# print(g)
queue=[]
d={}
pre={}
visited=[]
queue.append(start)
d[start]=0
pre[start]=-1
while queue:
x=queue.pop(0)
elist = glist2[x]
for i in elist:
if not i in visited and i!=start:
queue.append(i)
d[i]=d[x]+1
pre[i]=x
visited.append(i)
print(pre)
print(d)
print(visited)
order2=[]
order2.append(end)
def found(pre,start,end):
x=pre[end]
order2.append(x)
if x == -1:
return True
found(pre,start,x)
found(pre, start, end)
print(order2)
# def getKey(dict,values):
# return [k for k,v in dict.items() if v==values]
# wordLadder('hit','cog',['hot','dot','dog','lot','log'])
# print(ord('a'))#字母转换为Ascii数字
# print(chr(98))#Ascii数字转换为字母
# w='sstr'
# nw=w.replace(w[0],chr(ord(w[0])+1),1)
# print(nw)
'''
#周围区域问题:
给定二维平面,格点处为'X'或'O'.求出所有由'X'围成的区域
找到这样的区域后,将所有的O翻转成X即可
eg:X X X X X X X X
X O O X --> X X X X
X X O X X X X X
X O X X X O X X
此处只考虑四位相邻
反向思考最简单:哪些’O‘ 是应该保留的?
从上下左右四个边界往里走,凡是能碰到的’O‘,都是跟边界接壤的,应该保留
思路:
对于每一个边界上的'O'作为起点,做若干次广度优先搜素,对于碰到的'O',标记为其它某字符Y
最后遍历一遍整个地图,把所有的Y恢复恢复成'O'
把所有现有的'O'都改成'X'
'''
def aroundArea(matrix):
top=matrix[0]
bottom=matrix[-1]
left=[i[0] for i in matrix[1:row_len-1]]
right=[i[-1] for i in matrix[1:row_len-1]]
for i in range(0,len(top)):
if top[i]=='O':
bfs(matrix,0,i)
for i in range(0,len(bottom)):
if bottom[i]=='O':
bfs(matrix,row_len-1,i)
for i in range(0,len(left)):
if left[i]=='O':
bfs(matrix,i+1,0)
for i in range(0,len(right)):
if right[i]=='O':
bfs(matrix,i+1,col_len-1)
# print(matrix)
for i in range(0,row_len):
for j in range(0,col_len):
if(matrix[i][j]=='O'):
matrix[i][j]='X'
elif matrix[i][j]=='Y':
matrix[i][j]='O'
print(matrix)
# print(top,bottom,left,right)
def bfs(matrix,row,col):
queue=[]
visited=[]
queue.append((row,col))
while queue:
x=queue.pop(0)
l = [(x[0] - 1, x[1]), (x[0] + 1, x[1]), (x[0], x[1] - 1), (x[0], x[1] + 1)]#相邻四位
for i in l:
if not i in visited:
if i[0]>=0 and i[0]<row_len and i[1]>=0 and i[1]<col_len :
if matrix[i[0]][i[1]]=='O':
matrix[i[0]][i[1]]='Y'#标记为其它字符
queue.append(i)#只有相邻为'O',才入队
visited.append(i)
matrix[row][col]='Y'
print(visited)
matrix=[['X','X','X','X','X'],['X','O','X','O','X'],['X','O','O','O','X'],['X','X','O','X','X']]
row_len=len(matrix)
col_len=len(matrix[0])
aroundArea(matrix)