剑指offer--字符串的排列&&复杂链表的复制&&二叉搜索树与双向链表

题目:38题,多思考

输入一个字符串,打印出该字符串中字符的所有排列。

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例:

输入:s = "abc"
输出:["abc","acb","bac","bca","cab","cba"]

思路:回溯

class Solution:
    def permutation(self, s: str) -> List[str]:
        #标记
        c, res = list(s), []
        def dfs(x):
            if x == len(c) - 1:
                res.append(''.join(c))   # 添加排列方案
                return
            dic = set()
            for i in range(x, len(c)):
                if c[i] in dic: continue # 重复,因此剪枝
                dic.add(c[i])
                c[i], c[x] = c[x], c[i]  # 交换,将 c[i] 固定在第 x 位
                dfs(x + 1)               # 开启固定第 x + 1 位字符
                c[i], c[x] = c[x], c[i]  # 恢复交换
        dfs(0)
        return res

题目:

请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。

思路:通过哈希表创建新老链表的映射,实现新链表的next和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 None
        #因为添加入了新的random,所以不能使用原来的前驱节点一个一个复制节点的方法
        #为了找到当前节点的下一个random,这里可以用哈希表的方法,通过原链表与现链表各节点的对应关系来进行连线
        dic={}
        #首先创建新老链表各节点的映射
        cur=head
        while cur:
            dic[cur]=Node(cur.val)#Node(cur.val)就相当于在字典值的位置开辟了对应的节点,只不过该节点只有本身还没有next和random的指向。
            cur=cur.next
        #可以把这个字典想象成为两列,右边的一列只需要跟着左边的一列相对应的连线即可
        cur=head#cur需要重新获得头节点
        while cur:
            dic[cur].next=dic.get(cur.next)#对应原始节点先当与键,get(cur.next)相当于值,通过这两行代码就在新节点这一侧实现了连线
            dic[cur].random=dic.get(cur.random)
            cur=cur.next
        return dic[head]#把字典的值那一部分打印出来

 

题目:

输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。

 

思路:中序遍历加递归,中序遍历就可以实现有序链表,只需要把中序遍历二叉树的中间打印节点的部分换为前驱节点和当前节点的相互连接关系即可,最后还要实现首尾的循环。

代码:

"""
# 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':
        #首先知道二叉搜索树的性质,左子树都比根节点小,右子树都比根节点大
        #然后题目要求我们做出循环双向链表,也就是依次增大,那我们采用中序遍历的话自然就可以实现有序链表
        #中序遍历打印出来二叉搜索树的代码为:
        #dfs(root.left)
        #print(root.val)
        #dfs(root.right)这样打印出来的顺序是12345
        #所以我们需要做的就是把打印print的代码块部分修改,增加上链表的双向连接即可,就是pre.right=cur cur.left=pre

        #首先判断空树
        if not root:return 
        def dfs(cur):
            if not cur:return #说明已经超过了叶子节点,将代码return出来
            dfs(cur.left)#根据中序遍历代码先写第一步,遍历左子树
            #下面就分了两种情况,开始的self.pre是设为空的,所以根据self.pre来判断是否是头节点
            if self.pre:
                self.pre.right,cur.left=cur,self.pre
            else:
                self.head=cur#找到了头节点,先保存起来
            self.pre=cur#这时候的先驱节点就已经变为了cur,下一次递归就接在了上一个cur的下面,实现链表的连接
            #完成了中间代码块部分的修改,就该递归右子树
            dfs(cur.right)
        #出来递归函数之后还要有一些操作
        self.pre=None#开始的self.pre是没有值的
        dfs(root)#起始递归节点是头节点
        #递归结束之后还需要把头尾节点连接起来,实现循环链表
        self.head.left,self.pre.right=self.pre,self.head
        return self.head

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值