lc marathon 7.16

138. 复制带随机指针的链表

关键是 建立 旧节点->新节点 的映射

"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""

class Solution:
    def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
        dic={}
        p=head # p指向当前被复制的节点
        dumphead=Node(-1)
        q=dumphead# q指向复制链的最后一个节点,需要连接本轮复制的节点
        while(p!=None):
            node_c=Node(p.val)#进行复制
            q.next=node_c # 连接复制节点
            dic[p]=node_c # 加入映射
            q=q.next # q节点继续指向最后一个
            p=p.next # p节点前进
        # 复制random的指向
        p=head 
        q=dumphead.next # p,q 节点同步出发
        while(p!=None):
            if p.random!=None:
                q.random=dic[p.random]
            p=p.next
            q=q.next
        return dumphead.next
剑指 Offer II 092. 翻转字符
    # 遍历每一位 ,并假设 这一位 为第一个开始的1(或者最后一个0)(前面全0,后面全1) 的翻转次数
    # 为了将时间复杂度降到O(N)
    # 我们遍历每位时,需要该数前面1的个数,和后面0的个数
    # 在有字符串0的总数的情况下,需要每个位置后面0的个数
class Solution:
    def minFlipsMonoIncr(self, s: str) -> int:
        num_s=list(s)
        count_0=s.count('0') # 0的总个数
        num_0=[0 for i in range(len(s))] #存储每个位置后面0的个数
        if len(s)==1 or len(s)==0:
            return 0
        if s[0]=='1':  # 如果第一位是1,则后面为全部0
            num_0[0]=count_0
        elif s[0]=='0':
            num_0[0]=count_0-1 # 如果第一位是1,则后面为全部0的个数减一
        for i in range(1,len(num_s)):
            if num_s[i]=='1':
                num_0[i]=num_0[i-1]
            else:
                num_0[i]=num_0[i-1]-1
        mini=9999 # 用于存储最少翻转次数
        dic={'0':1,'1':0}
        for i in range(len(num_s)):
            #i 当前数 前面的数的个数
            pre0=count_0-dic[num_s[i]]-num_0[i]#当前数 前面0的个数
            pre1=i-pre0#当前数 前面1的个数
            mini=min(mini,pre1+num_0[i])
        return mini
面试题 08.09. 括号

记忆化存储+回溯 是真滴好用啊

def generateParenthesis( n: int) :

    return gen(n)

@cache
def gen(n):
    if n==0:
        return [""]
    if n==1:
        return ["()"]
    rs=set()
    for i in range(n-1):
        for pre in gen(i):
            for las in gen(n-i-1):
                rs.add(pre+'('+las+')')
                rs.add(pre+'()'+las)
                rs.add('('+pre+')'+las)
    return list(rs)


if __name__ == '__main__':
    print(generateParenthesis(3))
面试题 05.03. 翻转数位

求补码(为了兼容负数)bin(num & 0xfffffffff

class Solution:
    def reverseBits(self, num: int) -> int:
        if num==-1:
            return 32
        numbin=str(bin(num & 0xffffffff))[2:]#转化成2进制
        # 遍历每个数,我们需要到0时,记录在它之前连续的1的个数,并获得它之后连续1的个数
        pre=0 #记录在0之前连续1的个数 
        las=0 #记录在0之后连续1的个数
        i=0
        #0000
        maxo=0# 记录转换后 最长连续1的个数
        while(i<len(numbin)):
            if numbin[i]=='1': # 记录1的个数
                pre+=1
                i=i+1
            elif numbin[i]=='0':
                ori=i # 存储当前i的位置
                i=i+1 # 跳到下一位 
                while(i<len(numbin) and numbin[i]=='1'):
                    i+=1
                # 最终i跳到下一个0的位置 或者 len(numbin)
                las=i-ori-1 # 代表在0之后连续1的个数
                maxo=max(maxo,pre+las+1)
                pre=las # 
                las=0
        maxo=max(pre+1,maxo)
        return maxo
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值