链表python笔试题目_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="\t")

p = p.next

instance = ReorderLink() # 实例

head9 = instance(head9) # 实例可调用

print()

p = head9

print("排序后: ", end=" ")

while p is not None:

print(p.data, end="\t")

p = p.next

最后:

if hasattr(reader, "QQ"):

print(f"请{reader}加入交流群:6259 88679 !")

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值