本题目摘自《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 !")

python经典面试算法题1.4:如何对链表进行重新排序的更多相关文章

  1. python经典面试算法题1.3:如何计算两个单链表所代表的数之和

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.2 如何实现链表的逆序 [华为笔试题] 难度系数:⭐⭐⭐ ...

  2. python经典面试算法题1.2:如何从无序链表中移除重复项

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.2 如何实现链表的逆序 [蚂蚁金服面试题] 难度系数:⭐⭐ ...

  3. python经典面试算法题4.1:如何找出数组中唯一的重复元素

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. [百度面试题] 难度系数:⭐⭐⭐ 考察频率:⭐⭐⭐⭐ 题目描述 ...

  4. python经典面试算法题1.1:如何实现链表的逆序

    本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.1 如何实现链表的逆序 [腾讯笔试题] 难度系数:⭐⭐⭐ ...

  5. C++经典面试算法题

    转自:http://blog.csdn.net/f_r_e_e_x/article/details/50770907 //1.实现strcpy. char* MyStrCpy( char *pDest ...

  6. 2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案

    2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案 1.题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. ...

  7. python 经典排序算法

    python 经典排序算法 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.常见的内部排序算 ...

  8. 合并K个有序数组(链表)【字节跳动面试算法题】

    本题是本人字节跳动一面考的算法题原题是有序数组,一时没想到怎么解决数组的问题,但是如果给的是有序链表数组,则可以用下面的方法解决 可以利用最小堆完成,时间复杂度是O(nklogk),具体过程如下: 创 ...

  9. 剑指offer中经典的算法题之从头到尾打印链表

    话不多说上代码: 我自己的算法是: /** * public class ListNode { * int val; * ListNode next = null; * * ListNode(int ...

随机推荐

  1. Django+小程序技术打造微信小程序助手 ✌✌

    Django+小程序技术打造微信小程序助手 (一个人学习或许会很枯燥,但是寻找更多志同道合的朋友一起,学习将会变得更加有意义✌✌) 从零到一的完整项目开发实战过程,项目开发聚焦重要知识点,先原理后实战 ...

  2. vue中 props 多层组件嵌套传值

    如:三层嵌套. 父组件=>子组件=>孙子 1. 父组件引用子组件component11 , isShow传值给子组件component11 2. 子组件用  props 接受父组件的值, ...

  3. Luogu P2297 刷图 DP

    题目背景 loidc,LOI中的传说级哲♂学家,曾经创造一天内入坑maxlongint个弃坑0x7fffffff个的神奇纪录.目前,loidc最喜欢的游戏就是地下城与勇♂士. 题目描述 Loidc是一 ...

  4. Grid实现table表格布局

    HTML <div class="table"> <div class="th"> <div>日期</div> ...

  5. {每日一题}:四种方法实现打印feibo斐波那契数列

    刚开始学Python的时候,记得经常遇到打印斐波那契数列了,今天玩玩使用四种办法打印出斐波那契数列 方法一:使用普通函数 def feibo(n): """ 打印斐波那契 ...

  6. 基础安全术语科普(五)——crypter

    crypter(加壳):使病毒逃过反病毒软件检测的技术 UD类加壳病毒:只有%50至%25的软件能检测出是病毒. FUD类加壳病毒:完全不会被检测出来. 加壳技术有两个主要组件: 1.client — ...

  7. .NETCore下CI/CD之自动化测试

    前言 为了呼应<中国.NET开发者峰会2019上海站>,作为演讲嘉宾,我希望和各位同行建立更多的互动,为此,我特地将部分演讲内容,整理成文章先行发布.本文从零开始,一步一步的引导,从安装J ...

  8. 【网络安全】Dos攻击科普文

    目录 DOS攻击 什么是DOS攻击 攻击手段分类 具体的攻击方式举例 优秀博客参考 DDOS攻击 DOS攻击 什么是DOS攻击 DOS是Denial of Service的简称,用中文简单翻译就是拒绝 ...

  9. 数据结构(四十一)多路查找树(B树)

    一.多路查找树的背景 前面所讨论的查找算法都是在内存中进行的,它们适用于较小的文件,而对于较大的.存放在外存储器上的文件就不合适了,对于此类大规模的文件,即使是采用了平衡二叉树,在查找效率上仍然较低. ...

  10. 【从刷面试题到构建知识体系】Java底层-synchronized锁-2偏向锁篇

    上一篇通过构建金字塔结构,来从不同的角度,由浅入深的对synchronized关键字做了介绍, 快速跳转:https://www.cnblogs.com/xyang/p/11631866.html 本 ...