算法(11)-leetcode-explore-learn-数据结构-链表的经典问题

leetcode-explore-learn-数据结构-链表3

  • 1.反转一个链表
  • 2.移除链表元素
  • 3.奇偶链表
  • 4.回文链表
  • 5.小结

本系列博文为leetcode-explore-learn子栏目学习笔记,如有不详之处,请参考leetcode官网:https://leetcode-cn.com/explore/learn/card/linked-list/

所有例题的编程语言为python

1.反转一个链表

leetcode 206
思路1: 迭代求解,将当前结点next信息保存下来,然后将前一个节点的信息存入当前结点的next中。更新当前结点。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def reverseList(self, head):""":type head: ListNode:rtype: ListNode"""if head==None:return headpre_node=Nonecur_node=headwhile(cur_node):next_node=cur_node.nextcur_node.next=pre_nodepre_node=cur_nodecur_node=next_nodereturn pre_node   

思路2:
递归:假设链表的其余部分都已经被翻转,现在该如何翻转它前面的部分。由最后一个开始往前不断翻转
在这里插入图片描述

class Solution(object):def reverseList(self, head):""":type head: ListNode:rtype: ListNode"""if head==None or head.next==None:return headp=self.reverseList(head.next)   # 记录最后一个结点作为头指针用的。head.next.next=headhead.next=Nonereturn p

2.移除链表元素

删除链表中等于给定值 val 的所有节点。
思路:遍历链表的每一结点,如果值等于给定值将其删除即可。
注意点:要删除链表节点时,可以使用哑结点技巧,防止删原链表的头结点。最后返回时,返回dummy.next即可。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def removeElements(self, head, val):""":type head: ListNode:type val: int:rtype: ListNode"""dummy=ListNode(0)dummy.next=headpre_node=dummycur_node=dummy.nextwhile(cur_node):next_node=cur_node.nextif cur_node.val==val:pre_node.next=next_node  # 删除结点else:pre_node=cur_nodecur_node=next_nodereturn dummy.next

3.奇偶链表

给定一个单链表,把所有奇数节点和偶数节点(节点 编号的奇偶性)分别排在一起。
思路1:原来的链表分成奇偶两个子链表,然后将偶链表链接到奇链表后面。
没有使用额外的空间,直接从原来的链表中截取。

# Definition for singly-linked list.
class ListNode(object):def __init__(self, x):self.val = xself.next = Noneclass Solution(object):def oddEvenList(self, head):""":type head: ListNode:rtype: ListNode"""if head==None:return headeven_h=ListNode(0)even_node=even_hcur_node=headi=1while(cur_node):next_node=cur_node.nextif i %2==0:cur_node.next=None   # 将node.next的值给设置为零,能防止成环even_node.next=cur_nodeeven_node=even_node.nextpre_node.next=next_nodeelse:pre_node=cur_nodecur_node=next_nodei+=1cur_node=head.nextpre_node=headwhile(cur_node):print(pre_node.val)pre_node=cur_nodecur_node=cur_node.nextpre_node.next=even_h.nextreturn head        

4.回文链表

判断一个链表是否为回文链表。
o(n)时间复杂度,o(1)空间复杂度

思路1:可以先把链表装进数组中,判断数组中元素是否构成回文。数组的前后遍历比单链表方便。时间复杂度o(n),空间复杂度o(n)

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = Noneclass Solution(object):def isPalindrome(self, head):""":type head: ListNode:rtype: bool"""if not head or not head.next:return Truelst=[]p=headwhile(p):lst.append(p.val)p=p.nextreturn lst==lst[::-1]

思路2:翻转原链表,对照两个链表是否一致,如果回文链表应该是一致的,反之原链表不为回文链表。时间复杂度o(n),空间复杂度o(n)

# Definition for singly-linked list.
class ListNode(object):def __init__(self, x):self.val = xself.next = Noneclass Solution(object):def isPalindrome(self, head):""":type head: ListNode:rtype: bool"""if head==None or head.next==None:return True# 备份原链表head_be=ListNode(0)node=headnode_be=head_be    while(node):node_be.next=ListNode(node.val)node_be=node_be.nextnode=node.next# 转置原链表pre_node=Nonecur_node=headwhile(cur_node):next_node=cur_node.nextcur_node.next=pre_nodepre_node=cur_nodecur_node=next_node# 比较两个链表node_be=head_be.nextnode_af=pre_nodewhile(node_be and node_af):if node_be.val!=node_af.val:return Falsenode_be=node_be.nextnode_af=node_af.nextreturn True

思路三:避免使用 O(n)O(n) 额外空间的方法就是改变输入。

我们可以将链表的后半部分反转(修改链表结构),然后将前半部分和后半部分进行比较。比较完成后我们应该将链表恢复原样。虽然不需要恢复也能通过测试用例,因为使用该函数的人不希望链表结构被更改。

class Solution(object):def isPalindrome(self, head):""":type head: ListNode:rtype: bool"""if not head or not head.next:return True# 计算链表长度p1=headn=1while(p1.next):p1=p1.nextn+=1p1=headp2=headif n==2:if  head.val==head.next.val:return Trueelse:return False# 找链表中点for i in range(int(round(n/2.0))-1): # 0p1=p1.nexthalf_end=p1     # 前一半链表的最后一个节点# 翻转后一半链表p1=p1.nextpre_node=Nonefor i in range(int(n/2.0)): # 0,1next_node=p1.nextp1.next=pre_nodepre_node=p1p1=next_nodehalf_end.next=pre_nodep1=head# 比较前一半和翻转后的后一半。for i in range(int(round(n/2.0))): # 0,1p1=p1.nextfor i in range(int(n/2)):# 0,1if p1.val!=p2.val:return Falsep1=p1.nextp2=p2.nextreturn True

5.小结

1.使用链表时不易调试,自己多尝试几个测试用例总是很有用的,通过输出链表节点的值来观测代码运行情况。

2.多指针时,为指针设定合适的名称,防止自己被搞混

3.单链表操作时,储存前一个节点的信息往往是有效的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445042.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux线程池的设计

我设计这个线程池的初衷是为了与socket对接的。线程池的实现千变万化,我得这个并不一定是最好的,但却是否和我心目中需求模型的。现把部分设计思路和代码贴出,以期抛砖引玉。个人比较喜欢搞开源,所以大家如果觉得有什么需要改善的…

leetcode121买卖股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 注意你不能在买入股票前卖出股票。 示例 1: 输入: [7,1,5,3,6,…

epoll的内核实现

epoll是由一组系统调用组成。 int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout); select/poll的缺点在于&#xff1…

leetcode322 零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。 示例 1: 输入: coins [1, 2, 5], amount 11 输出: 3 解释: 11 5 5 1 示例 2: 输入: coins [2],…

leetcode538 把二叉搜索树转换成累加树

给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。 对于每一个点来说,自己的父,和自己父的右子树都是大…

leetcode15 三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a b c 0 ?找出所有满足条件且不重复的三元组。 注意:答案中不可以包含重复的三元组。 例如, 给定数组 nums [-1, 0, 1,…

leetcode19. 删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 示例: 给定一个链表: 1->2->3->4->5, 和 n 2. 当删除了倒数第二个节点后,链表变为 1->2->3->5. 说明: 给定的 n 保证是有效…

python模块(5)-Matplotlib 简易使用教程

Matplotlib简易使用教程0.matplotlib的安装1.导入相关库2.画布初始化2.1 隐式创建2.2 显示创建2.3 设置画布大小2.4 plt.figure()常用参数3.plt. 能够绘制图像类型3.1等高线3.2 箭头arrow4.简单绘制小demodemo1.曲线图demo2-柱状、饼状、曲线子图5.plt.plot()--设置曲线颜色,粗…

leetcode20 有效的括号

给定一个只包括 (,),{,},[,] 的字符串,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。 示…

leetcode1 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums [2, 7, 11, 15], t…

leetcode3 无重复字符最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 示例 2: 输入: "bbbbb" 输出: 1 解释: 因为无重复字符…

Linux(6)-命令行的使用,history,shell脚本

命令行的使用,shell脚本1.终端shell,man1.1 Ctrlr--匹配查找历史命令1.2 history [n] --列出历史命令1.3!--执行历史命令2.shell 编程2.1 shell脚本2.2 注释2.3 指明所用的shell2.4 支持函数2.5 使用变量2.6 解析命令行参数2.7 if, for, case, while2.8 shell脚本中…

程序以及论文

本人长期承接大学计算机专业的毕业设计和论文的编写。 主要开发语言C,C (windows或linux平台皆可),php,c#,VC 。 课题内容可以是 管理系统,可以是 网站设计开发 可以是 网络聊天 可以是 应用…

Github(1)-概览,初始化仓库

Github网页-本地git1.github网页1.1 主要界面1.1.1github主页1.1.2仓库主页1.1.3 个人页面1.2 注册github账号1.3 新建平台仓库2.git-本地仓库2.1 git本地仓库的三个区域2.2 创建一个本地仓库GitHub 本质上是一个代码托管平台,它提供的是基于 Git 的代码托管服务。G…

leetcode16 最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。 例如,给定数组 nums [-1,2,1,-4], 和 target 1…

leecode11 盛水最多的容器

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多…

leecode26 删除排序数组中的重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 示例 1: 给定数组 nums [1,1,2…

leecode53 最大子序列和

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 思路:…

Github(3)-本地文件管理

使用github 托管代码简单使用教程--本地文件管理1.基本概念2.本地文件管理2.1 git add2.2 git status2.3 git commit2.3 git log2.5 git reset --hard 版本回退2.6 git reflog2.7 git diff2.8 git checkout --file 工作区文件恢复2.9 git rm 删除版本库里的文件廖雪峰老师博文学…

leecode62 不同路径

示例 1: 输入: m 3, n 2 输出: 3 解释: 从左上角开始,总共有 3 条路径可以到达右下角。 1. 向右 -> 向右 -> 向下 2. 向右 -> 向下 -> 向右 3. 向下 -> 向右 -> 向右 示例 2: 输入: m 7, n 3 输出: 28 思路:太过于简单&#xf…