leetcoe-指剑offer-2021-08-09

这篇博客深入探讨了复杂链表的复制、二叉搜索树转化为双向链表的算法,以及如何在数据流中高效计算中位数。同时,文章还介绍了数组中的逆序对计数方法,使用归并排序实现,并讲解了n个骰子点数概率的计算。此外,还讨论了解决圆圈中最后剩余数字的问题以及如何在不使用加减乘除的情况下进行加法运算。这些内容涵盖了基础数据结构和算法的应用,对于提升编程能力大有裨益。
摘要由CSDN通过智能技术生成
  1. 剑指 Offer 35. 复杂链表的复制
  2. 剑指 Offer 36. 二叉搜索树与双向链表
  3. 剑指 Offer 41. 数据流中的中位数
  4. 剑指 Offer 51. 数组中的逆序对
  5. 剑指 Offer 60. n个骰子的点数
  6. 剑指 Offer 62. 圆圈中最后剩下的数字
  7. 剑指 Offer 65. 不用加减乘除做加法
剑指 Offer 35. 复杂链表的复制

比普通链表多了一个random指针,因此如果按照链表next的顺序遍历一个个新建,无法知道random指向的节点在哪,所以需要用一个哈希表去一个个查询random指向的节点在哪。

"""
# 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: 'Node') -> 'Node':
        if not head:
            return
        dic ={}
        cur = head
        while cur:
            dic[cur]=Node(cur.val) # 这里相当于将(原节点cur,新建节点cur)存入dic
            cur = cur.next
        cur =head
        while cur: #dict.get()是返回对应键的值,如果不存在则返回default
            dic[cur].next = dic.get(cur.next) # 前者相当于取出新建节点,将他的next指向(cur.next, 新建节点)中的新建节点
            dic[cur].random = dic.get(cur.random) #同上,只不过是random
            cur = cur.next
        return dic[head]
剑指 Offer 36. 二叉搜索树与双向链表

二叉搜索树的中序遍历是递增序列

"""
# Definition for a Node.
class Node:
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
"""
class Solution:
    def treeToDoublyList(self, root: 'Node') -> 'Node':
        def dfs(node): # 深度优先,中序遍历
            if not node:
                return
            dfs(node.left)
            if self.pre:
                self.pre.right = node #将1节点的right指向2节点
                node.left = self.pre #将2节点的left指向1节点
            else:
                self.head = node
            self.pre = node
            dfs(node.right)
        if not root: return
        self.pre = None
        dfs(root)
        self.head.left = self.pre #将头部节点和尾部节点相连
        self.pre.right = self.head
        return self.head
剑指 Offer 41. 数据流中的中位数
class MedianFinder:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.A = []
        self.B = []


    def addNum(self, num: int) -> None:
        if len(self.A)==len(self.B):
            heappush(self.B,-num)
            tmp = -heappop(self.B)
            heappush(self.A, tmp)
        else:
            heappush(self.A,num)
            tmp = -heappop(self.A)
            heappush(self.B, tmp)



    def findMedian(self) -> float:
        return self.A[0] if len(self.A)!=len(self.B) else (self.A[0]-self.B[0])/2.0
剑指 Offer 51. 数组中的逆序对

归并排序

class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        def merge_sort(l,r):
            if l>=r: #直到分成单个元素
                return 0
            m=(l+r)//2
            res = merge_sort(l,m)+merge_sort(m+1,r) # 递归分割
            i,j = l, m+1 # 排序
            tmp[l:r+1] = nums[l:r+1] # 先复制一遍数字到tmp,排序在原nums里
            for k in range(l,r+1):
                if i == m+1: # 说明左边的数字已经全都添加到排序后的list里面了
                    nums[k] = tmp[j]# 将右边的待排序数字加入排序后的list里
                    j+=1 # 这里不存在逆序对,因为题目要求是左边数字大于右边的情况,此时左边数组已经空了 
                elif j == r+1 or tmp[i]<=tmp[j]: # 添加左边数字,说明其小于右边数组,不存在逆序对,或者是右边数组已经全部添加到排序后的list里面了,虽然左边数字大,但是没有比它小的右边数字了,不存在逆序对
                    nums[k] = tmp[i]
                    i+=1
                else: # 左右数组都还有待排序的数字,并且右边数字更小,此时符合逆序对的条件
                    nums[k] = tmp[j]
                    j+=1
                    res+=m-i+1 # 这里加上的是左边数组内目前还有的数字个数
            return res
        tmp = [0 for _ in range(len(nums))]
        return merge_sort(0,len(nums)-1)
剑指 Offer 60. n个骰子的点数
class Solution:
    def dicesProbability(self, n: int) -> List[float]:
        dp = [1/6]*6
        for i in range(2,n+1):
            tmp=[0]*(5*i+1)
            for j in range(len(dp)):
                for k in range(6):
                    tmp[j+k] += dp[j]/6
            dp = tmp
        return dp
剑指 Offer 62. 圆圈中最后剩下的数字
class Solution:
    def lastRemaining(self, n: int, m: int) -> int:
        x = 0
        for i in range(2,n+1):
            x = (x+m)%i
        return x
剑指 Offer 65. 不用加减乘除做加法
class Solution:
    def add(self, a: int, b: int) -> int:
        x = 0xffffffff
        a,b = a&x,b&x
        while b:
            a,b = (a^b),(a&b)<<1 & x # &x是为了防止溢出32位
        return a if a<=0x7fffffff else ~(a^x)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值