zoukankan      html  css  js  c++  java
  • python经典面试算法题1.4:如何对链表进行重新排序

    本题目摘自《Python程序员面试算法宝典》,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中。

    1.4 对链表按照如下要求重新排序
    【微软笔试题】

    难度系数:⭐⭐⭐
    考察频率:⭐⭐⭐⭐

    题目描述:

    给定链表L0 -> L1 -> L2 -> … -> Ln-1 -> Ln ,把链表重新排序为 L0 -> Ln -> L1 -> Ln-1 -> L2 … 。要求:(1)在原来链表的基础上进行排序,即不能申请新的结点;(2)只能修改结点的next域,不能修改数据域。

    分析解答:
    当我们在笔试过程中遇到这种问题,一下子是没有什么思路的,我们要做的方法是把复杂问题拆解为简单问题。
    就这一题而言我们可以把它分为三个步骤,(1)首先找到链表的中间结点;(2)对链表的后半部分子链表进行逆序;(3)把链表的前半部分子链表与逆序后的后半部分子链表进行合并,这里合并的思路是分别从两个链表各取一个结点进行合并。

    步骤一
    我们使用两个指针从链表的第一个结点开始同时遍历,快指针每次走两步,慢指针每次走一步,当快指针到达链表尾部时,慢指针恰好到达链表中部。

    def find_mid_node(head):
        if head is None or head.next is None:
            return head
        fast = head
        slow = head
        prev = slow
        while fast is not None and fast.next is not None:
            fast = fast.next.next
            prev = slow
            slow = slow.next
        prev.next = None
        return slow  # 下半段的head
    

    步骤二
    这一步在我前面的博客文章中有写,可以点击此处跳转

    def reverse(head):  #
        p = head
        if p is None or p.next is None:
            return p
        q = p
        p = p.next
        while p is not None:
            tmp = p.next
            p.next = q
            if q == head:
                q.next = None
            q = p
            p = tmp
        return q
    
    

    步骤三
    这个函数传入前半部分的第一个结点和后半部分的第一个结点,cur1指向前半部分的第一个结点,cur2指向后半部分的第一个结点,tmp指向cur1后面的结点,然后令cur1的next指向cur2,接着cur1后移指向此时的tmp,然后让tmp再指向记住cur2的后面一个结点,令cur2的next指向此时的cur1,这样我们就完成了后半部分的第一个结点插入到前半部分,就这样一直往后,直到cur1到达最后一个结点,全部结点插入完成。

    # 插入
    def reorder(head1, head2):
        cur1 = head1
        cur2 = head2
        tmp = None
        while cur1.next is not None:
            tmp = cur1.next
            cur1.next = cur2
            cur1 = tmp
    
            tmp = cur2.next
            cur2.next = cur1
            cur2 = tmp
    
        cur1.next = cur2  # 无论cur2是不是None,cur的next都应该指向cur2
    

    把三个函数封装到一个类中
    我们定义一个类,把上面三个函数都放在类中,并且令类的实例变成可调用对象。

    class ReorderLink:
        @staticmethod
        def find_mid_node(head):
            if head is None or head.next is None:
                return head
            fast = head
            slow = head
            prev = slow
            while fast is not None and fast.next is not None:
                fast = fast.next.next
                prev = slow
                slow = slow.next
            prev.next = None
            return slow  # 下半段的head
    
        @staticmethod
        def reverse(head):  #
            p = head
            if p is None or p.next is None:
                return p
            q = p
            p = p.next
            while p is not None:
                tmp = p.next
                p.next = q
                if q == head:
                    q.next = None
                q = p
                p = tmp
            return q
    
        @staticmethod
        def reorder(head1, head2):
            cur1 = head1
            cur2 = head2
            tmp = None
            while cur1.next is not None:
                tmp = cur1.next
                cur1.next = cur2
                cur1 = tmp
    
                tmp = cur2.next
                cur2.next = cur1
                cur2 = tmp
    
            cur1.next = cur2  # 无论cur2是不是None,cur的next都应该指向cur2
    
        def __call__(self, link_head):
            before = link_head
            rest =self.find_mid_node(before)
            rest = self.reverse(rest)  # 反转
            self.reorder(before, rest)
            return link_head
    
    

    测试
    构造一个链表,创建一个类的实例,调用类的实例。

    class Node:  # 结点类
        def __init__(self, data=None):
            self.data = data
            self.next = None
    
    class LinkList: # 链表
        def __init__(self):
            self.head = None
    
        def append(self, x):
            if self.head is None:
                self.head = Node(x)
                return self
            p = self.head
            while p.next is not None:
                p = p.next
            p.next = Node(x)
            return self
    
    
    link1 = LinkList()
    link1.append(1).append(2).append(3).append(4).append(5).append(6)
    
    head9 = link1.head
    
    p = head9
    print("排序前: ", end=" ")
    while p is not None:
        print(p.data, end="	")
        p = p.next
    
    instance = ReorderLink()  # 实例
    head9 = instance(head9)  # 实例可调用
    print()
    
    p = head9
    print("排序后: ", end=" ")
    while p is not None:
        print(p.data, end="	")
        p = p.next
    


    最后:

    if hasattr(reader, "QQ"):
    	print(f"请{reader}加入交流群:6259 88679 !")
    
  • 相关阅读:
    HadoopDB:混合分布式系统
    分布式一致性
    Hadoop和RDBMS的混合系统介绍
    《Facebook效应》
    《程序员的思维修炼》
    KMP算法实现
    关于毕业季照片分享的思考
    SDN:软件定义网络
    退出域不能够重新加入域,郁闷呀
    ◆聚会时可以玩的游戏◆
  • 原文地址:https://www.cnblogs.com/duanming/p/11830263.html
Copyright © 2011-2022 走看看