LeetCode-图-Hard

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步




839. Similar String Groups 相似字符串组

similar用来判断两个单词是否相似
1.DFS
挑选一个找到所有与他相似的词 取出
再在相似词中取出一个 重复 直到无法再取出 则已经没有单词可以进入这个集合
2.并查集
将相似的放进一个集合中

def similar(a,b):
    dif = 0
    l=len(a)
    for i in range(l):
        if a[i]!=b[i]:
            dif+=1
            if dif>2:
                return False
    return True

def numSimilarGroups(A):
    """
    :type A: List[str]
    :rtype: int
    """
    aset = set(A)
    res=0
    while aset:
        st = aset.pop()
        res+=1
        q = [st]
        while q:
            s = q.pop(0)
            tmp = aset.copy()
            while tmp:
                i = tmp.pop()
                if similar(s,i):
                    aset.remove(i)
                    q.append(i)
    return res

def numSimilarGroups2(A):
    """
    :type A: List[str]
    :rtype: int
    """
    def find(node):
        if parent[node]!=node:
            parent[node] = find(parent[node])
        return parent[node]
    
    def union(x,y):
        parent[find(x)]=find(y)
        
    A=list(set(A))
    parent = {x:x for x in A}
    for i in range(len(A)):
        for j in range(i+1,len(A)):
            if similar(A[i],A[j]):
                union(A[i],A[j])
    
    return len([1 for k,v in parent.items() if k==v])


854. K-Similar Strings 相似度为 K 的字符串

两个字符串从开始一次比较 若整串字符串都相等直接返回0
单个位置字符相等时跳过
直到第i个位置A[i]!=B[i]
此时我们需要在B中i后面的位置上找可以替换的位置j A[i]=B[j] (j>i)
我们使用query来储存B中能够替换的位置
这里有两种特殊情况:
1.B[j]==A[j]
这个情况下 本来j位置两个字符串是相同的 调换位置后i处相等了 但j处从相等变成了不等 这样的替换是没有意义的 所以排除
2.A[j]==B[i]
此时如果B的i,j对换 这样两个字符串的i,j两处位置都相同了 这是最理想的情况 遇到这种情况时 无序继续寻找 直接保存这个情况 退出替换
我们一次遍历query中的情况:
替换位置后A,B在i之前已经相等了 我们可以截断 将A[i+1:] B[i+1:]当做两个新的字符串考虑

def kSimilarity(A, B):
    """
    :type A: str
    :type B: str
    :rtype: int
    """    

    def replace(A,B):
        if ''.join(B)==A:
            return 0
        k = 99999
        query = []
        for i in range(len(A)):
            if A[i]==B[i]:
                continue
            pos = i
            best = False
            find = False
            for j in range(i+1,len(A)):
                if B[j]!=A[i] or B[j]==A[j]:
                    continue
                find = True
                if A[j] == B[i]:
                    best = True
                    query=[]
                    query.append(j)
                    break
                
                query.append(j)
            if best or find:
                break
            
        for x in query:
            B[x],B[pos] = B[pos],B[x]
            k = min(k,1+replace(A[pos+1:],B[pos+1:]))
            B[x],B[pos] = B[pos],B[x]
        
        return k


928. Minimize Malware Spread II 尽量减少恶意软件的传播 II

注意是从initial中去除一个 不是所有的点
直接遍历initial中所有点 使用bfs 计算每一种情况下的感染个数 取最小的位置

def minMalwareSpread(graph, initial):
    """
    :type graph: List[List[int]]
    :type initial: List[int]
    :rtype: int
    """
    N = len(graph)
    link = {}
    for i in range(N):
        link[i] = [x for x in range(N) if graph[i][x]==1]
    
    res=-1
    mincount= 99999
    if not initial:
        return 0
    initial.sort()
    def bfs(pos):
        query = initial[:]
        query.remove(pos)
        visit = {x:0 for x in range(N)}
        visit[pos]=1
        ret = len(query)
        while query:
            x = query.pop(0)
            for next in link[x]:
                if visit[next]==0 and graph[x][next]==1:
                    query.append(next)
                    visit[next]=1
                    ret+=1
        return ret
    
    for i in initial:
        ans = bfs(i)
        if ans<mincount:
            mincount = ans
            res = i
    return res


996. Number of Squareful Arrays 正方形数组的数目

函数sqr判断两数之和x是否是完全平方数
1.将A中各位值中两数之和为完全平方数的位置相连 构成关系图graph
如果存在某一位置不和其他相连 及没有任何一个数可以和他构成完全平方数 则该序列A没有符合条件的数组 返回0
判断起始位置:
只有单条连线的位置(只能和一个数构成完全平方数)的值必定放在开头或者结尾
如果这样的位置不是两个或者零个 那么返回0
如果是两个 则从这两个位置开始去寻找
如果是零个 那么需要从所有位置开始寻找
寻找函数 find
res保存已有的序列 pos当前的序列 g去除已使用的位置的关系图
如果res包含了所有的A内点 那么说明找到了一种排序方式
将这个结果保存到map result中 去除重复
这种方法按位置进行分析 但是有许多位置上的值其实是一样的 所以造成了时间上的浪费
2.按照数值来分析 统计每个值的出现个数 使用一个数组记录可以同对应的值构成完全平方数的数值
同样我们过滤掉无法构成完全平方数的情况
遍历每个值为开头的情况
find(value,lastnum)
value:为当前的数值
lastnum:剩余的值个数
在可以同value构成完全平方数的值的数组中遍历(i) 继续find(i,lastnum-1)

import copy
def sqr(x):
    import math
    if math.sqrt(x)==int(math.sqrt(x)):
       return True
    return False

def numSquarefulPerms(A):
    """
    :type A: List[int]
    :rtype: int
    """
    graph = {x:[] for x in range(len(A))}
    
    for i in range(len(A)):
        for j in range(i+1,len(A)):
            if sqr(A[i]+A[j]):
                graph[i].append(j)
                graph[j].append(i)
    
    ##查找是否有无法构成完全平方数的位置
    ck = [0 for x in graph.keys() if len(graph[x])==0]
    if ck:
        return 0
    
   
    def find(res,pos,g):
        res.append(pos)
        #print([A[i] for i in res],pos,g)
        if len(res)==len(A):
            ret = [A[i] for i in res]
            result[str(ret)]=ret
        if not g[pos]:
            return
        l={}
        for i in g[pos]:
            l[A[i]]=i

        for i in l.values():
            tmpg = copy.deepcopy(g)
            for j in tmpg[pos]:
                tmpg[j].remove(pos)
            tmpg[pos]=[]
            #print("begin:",res,i,tmpg)
            find(res[:],i,tmpg)

    result={}
    
    ##只能和其它一个数构成的完全平方数的位置 可以当做开始或结尾 
    ##这样的位置只能有0或2个
    start = [x for x in graph.keys() if len(graph[x])==1]
    if len(start)!=2 and len(start)!=0:
        return 0
    if len(start)==0:
        start = list(range(len(A)))
    for x in start:
        #print("start",x,A[x])
        l = []
        find(l,x,graph)
            
    print(result.values())
    return len(result)

def numSquarefulPerms2(A):
    """
    :type A: List[int]
    :rtype: int
    """
    import collections
    
    count = collections.Counter(A)
    graph = {x:[] for x in count}
    for i in count:
        for j in count:
            if sqr(i+j):
                graph[i].append(j)
                
    ck = [0 for x in graph.keys() if len(graph[x])==0]
    if ck:
        return 0
    
    def find(value,lastnum):
        count[value] -= 1
        if lastnum==0:
            ans = 1
        else:
            ans = 0
            for i in graph[value]:
                if count[i]:
                    ans += find(i,lastnum-1)
        count[value] +=1
        return ans
    start= list(count)
    res = 0
    for i in start:
        res += find(i,len(A)-1)
    return res


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值