python经典面试算法题1.1:如何实现链表的逆序
本题目摘自《Python程序员面试算法宝典》,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中。
1.1 如何实现链表的逆序
【腾讯笔试题】
难度系数:⭐⭐⭐
考察频率:⭐⭐⭐⭐
题目描述:
给定一个带头结点的单链表,请将其逆序。即如果单链表原来为 head -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7,那么逆序后变为 head -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1。
解答
构造结点类和单链表类
class Node:
def __init__(self, data, next):
self.data = data
self.next = next
class SingleLink:
def __init__(self, head):
self.head = head
方法一:就地逆序(推荐,好理解)
主要思路:在遍历链表的时候,修改当前结点的指针域指向,让它指向它的前驱结点。
时间复杂度:O(n)
def reverse(link: SingleLink):
if link.head is None or link.head.next is None:
return None
cur = link.head.next # cur指向第一个结点
pre = link.head # pre指向头结点
while cur.next is not None: # 如果cur不是最后一个结点
ne = cur.next # ne记住当前结点的下一个结点
if pre != link.head: # 如果cur不是第一个结点
cur.next = pre # 把当前结点的next指向前一个结点
else:
cur.next = None
pre = cur # pre结点后移到当前结点
cur = ne # 当前结点后移一位
ne = ne.next # ne结点后移一位
# cur指向tail了
cur.next = pre # 当cur指向了最后一个结点,循环结束,把最后一个结点指向倒数第二个结点
link.head.next = cur # head指向最后一个结点,即cur
方法二:插入法(推荐,好理解)
主要思路:从链表的第二个结点开始,把遍历到的结点插入到头结点的后面,直到遍历结束。
时间复杂度:O(n)
def reverse2(link: SingleLink):
if link.head is None or link.head.next is None: # 空
return link.head
cur = link.head.next.next # 记住第二个结点
link.head.next.next = None # 第一个结点的指针从指向第二个结点变成None
while cur is not None: # 当第二个结点不是None的时候
next = cur.next # next等于第二个结点的next即第三个结点
cur.next = link.head.next # 第二个结点的next指向第一个结点
link.head.next = cur # head的next也从指向第一个结点变成指向第二个结点
cur = next # cur开始指向第三个结点, 如此循环下去
方法三:递归法(不推荐,算法实现难度大,需要额外的压栈和弹栈,有性能下降)
主要思路:先把除了第一个结点以外的结点逆序,接着把第一个结点添加到子链表的后面。
时间复杂度:O(n)
def RecursiveReverse(head):
# 如果链表为空,或者只有一个元素
if head is None or head.next is None:
return head
else:
# 反转后面的结点
newhead = RecursiveReverse(head.next)
# 把当前遍历的结点加到后面结点逆序后链表的尾部
head.next.next = head
head.next = None
return newhead
def Reverse(head):
if head is None:
return
first_node = head.next
newhead = RecursiveReverse(first_node)
# 将头结点指向逆序后链表的第一个结点
head.next = newhead
return newhead
测试
i = 1
tmp = Node(i, None)
head = Node(None, tmp)
while i < 8:
tmp.next = Node(i, None)
tmp = tmp.next
i += 1
print("正序是: ", end="")
cur = head
while cur.next is not None:
cur = cur.next
print(cur.data, end=" ")
print()
link1 = SingleLink(head)
reverse(link1)
print("逆序是: ", end="")
cur = link1.head
while cur.next is not None:
cur = cur.next
print(cur.data, end=" ")
# 输出:
正序是: 1 1 2 3 4 5 6 7
逆序是: 7 6 5 4 3 2 1 1
欢迎小伙伴们加入我创建的python交流群:625988679

python经典面试算法题1.1:如何实现链表的逆序的更多相关文章
- python经典面试算法题1.4:如何对链表进行重新排序
本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.4 对链表按照如下要求重新排序 [微软笔试题] 难度系数: ...
- python经典面试算法题1.3:如何计算两个单链表所代表的数之和
本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.2 如何实现链表的逆序 [华为笔试题] 难度系数:⭐⭐⭐ ...
- python经典面试算法题1.2:如何从无序链表中移除重复项
本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. 1.2 如何实现链表的逆序 [蚂蚁金服面试题] 难度系数:⭐⭐ ...
- python经典面试算法题4.1:如何找出数组中唯一的重复元素
本题目摘自<Python程序员面试算法宝典>,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中. [百度面试题] 难度系数:⭐⭐⭐ 考察频率:⭐⭐⭐⭐ 题目描述 ...
- C++经典面试算法题
转自:http://blog.csdn.net/f_r_e_e_x/article/details/50770907 //1.实现strcpy. char* MyStrCpy( char *pDest ...
- 2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案
2021字节跳动校招秋招算法面试真题解题报告--leetcode19 删除链表的倒数第 n 个结点,内含7种语言答案 1.题目描述 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点. ...
- python 经典排序算法
python 经典排序算法 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.常见的内部排序算 ...
- php最常见最经典的算法题
1.一群猴子排成一圈,按1,2,…,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫 ...
- 合并K个有序数组(链表)【字节跳动面试算法题】
本题是本人字节跳动一面考的算法题原题是有序数组,一时没想到怎么解决数组的问题,但是如果给的是有序链表数组,则可以用下面的方法解决 可以利用最小堆完成,时间复杂度是O(nklogk),具体过程如下: 创 ...
随机推荐
- Unicode 和 UTF-8 之间的关系
一.ASCII 码 我们知道,计算机内部,所有信息最终都是一个二进制值.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte).也就是说,一个 ...
- 解决window.onload延迟加载问题
window.onload方法,表示当页面所有的元素都加载完毕,并且所有要请求的资源也加载完毕才触发执行function这个匿名函数里边的具体内容.这样肯定保证了代码在domReady之后执行.使用w ...
- C语言--计算数组的平均值
//数组 int main() { ]; double sum = 0.0; ; int x; scanf("%d", &x); ) { muber[cnt] = x; c ...
- POJ1017&&UVA311 Packets(中文题面版)
感谢有道翻译--- Description A工厂生产的产品是用相同高度h的方形包装,尺寸为1* 1,2 * 2,3 * 3,4 * 4,5 * 5,6 6.这些产品总是以与产品高度h相同,尺寸为66 ...
- lua多线程解决方案
直观的讲:lua并不支持多线程,lua语言本身具有携程功能,但携程仅仅是一种中继器. lua多线程的目的:有并发需求时,共享一些数据. 例如使用lua写一个并发服务器.用户登陆之后,用户数据储存在lu ...
- postman常用断言
1.Code is 200 断言状态码是200 2.contains string 断言respoonse body中包含string 3.json value check (检查JSON值)
- 全平台正向tcp端口转发工具rinetd的使用
Linux下做地址NAT有很多种方法.比如haproxy.nginx的4层代理,linux自带的iptables等都能实现.其实,Linux下有一个叫rinetd的工具,安装简单,配置也不复杂. 下载 ...
- 理解JavaScript中的堆和栈
这里先说两个概念:1.堆(heap)2.栈(stack)堆 是堆内存的简称.栈 是栈内存的简称.说到堆栈,我们讲的就是内存的使用和分配了,没有寄存器的事,也没有硬盘的事.各种语言在处理堆栈的原理上都大 ...
- libevent::bufferevent
#include <cstdio> #include <netinet/in.h> #include <sys/socket.h> #include <fcn ...
- Java 异常处理的 20 个最佳实践,你知道几个?
异常处理是 Java 开发中的一个重要部分,是为了处理任何错误状况,比如资源不可访问,非法输入,空输入等等.Java 提供了几个异常处理特性,以try,catch 和 finally 关键字的形式内建 ...