本题目摘自《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. 编译 lame for iOS

    网上找了许多编译lame的教程,结果都是编译失败,多次尝试后发现是编译脚本放错路径了,记录下编译的过程,把编译脚本放到源码文件夹中和修改编译脚本中的目录是关键: 一.首先去Lame官网 http:// ...

  2. Python3 解决 ModuleNotFoundError: No module named 'pygal.i18n' 问题

    在获取国别码集通过导入模块pygal报以下问题: from pygal.i18n import COUNTRIES  解决方法: 安装模块 pip3 install pygal_maps_world ...

  3. 我们一起学Python之——认识Python"规则"

    前言: 开学后,跟预想的一样,开学第一天我们就开了Python,虽然之前早就预料到了,但对于一直学Java的我来说,内心还是有一些涟漪的.总归还是要接受的,还不如振作起来,认真对待.我决定从最简单并且 ...

  4. MySQL 5.7安装最佳实践

    MySQL 5.7安装最佳实践 1.环境准备OS: CentOS Linux release 7.4.1708 (Core) for VMwareMySQL: mysql-5.7.24-linux-g ...

  5. Java表达式计算转型规则

    本题答案应为:B.C.D ------------知识点------------ Java表达式转型规则由低到高转换(例如int 到 double): 1.所有的byte,short,char型的值将 ...

  6. Mysql多数据库备份

    备份数据脚本 #!/bin/bash # date是linux的一个命令 date [参数] [+格式] time=` date +%Y_%m_%d_%H_%M_%S ` # 备份输出路径 backu ...

  7. wwindows权限认识(用户及用户组)

    windows权限认识(用户及用户组) Windows系统内置了许多本地用户组,这些用户组本身都已经被赋予一些权限(permissions),它们具有管理本地计算机或访问本地资源的权限.只要用户账户加 ...

  8. 【websocket】spring boot 集成 websocket 的四种方式

    集成 websocket 的四种方案 1. 原生注解 pom.xml <dependency> <groupId>org.springframework.boot</gr ...

  9. Dropzone.js

    2015-11-25 发布 DropzoneJS 官网没有中文版的,很多东西只能跟着自己的感觉去理解,有些地方把握不了是否准确,在网上搜了一下中文版,看到一位大神简易的中文版 个人觉得和原官网对比着看 ...

  10. FTPClient连续读取文件

    最近在使用FTPClient连续读取ftp上的多个文件内容时,遇到了两个问题: 1. 在for循环中,FTPClient只能读取到第一个文件内容,读取第二个时遇到NPE问题. 2. 遇到程序锁死. 下 ...