赞
踩
努力汇总链表题目,好好干饭,好好努力,好好加油哦
实现一种算法,删除单向链表中间的某个节点(即不是第一个或最后一个节点)
输入:删除单向链表a->b->c->d->e->f中的节点c
结果:不返回任何数据,但该链表变为a->b->d->e->f
链表中的每一个node有两个属性 一个是 val 一个是next表方向
所以想要删掉某特定的node,只要改变这个node的这两个属性,使之变成下一个node的两个属性
即
node.val = node.next.val
node.next = node.next.next
class Node:
"""
定义节点Node
"""
def __init__(self,val=0,next=None):
self.val = val
self.next = next
def deleteNode(node):
node.val = node.next.val
node.next = node.next.next
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
把这个修改一下,就很明显了思路:
输入: 1->2->3->4->5->NULL
输出:NULL<-1<-2<-3<-4<-5
思路:
当输入头节点的时候,需要改变方向和next
用三个值 pre,cur,nxt来改变方向和赋值。
首先是 初始化 pre = None ; cur =0
赋值 nxt = cur.next
然后把cur的方向 指向在 pre,即 cur.next = pre;
然后把pre 和cur往后移动 即 pre = cur ; cur = nxt
重复下去,终止条件是 cur is None, 这个时候return pre即是倒转的链表
def reverseList(head):
#初始化
pre, cur = None , head
while cur:
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
return pre
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的
(1) l1 和 l2 均按 非递减顺序 排列
(2)两个链表的节点数目范围是 [0, 50]
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
输入:l1 = [], l2 = []
输出:[]
输入:l1 = [], l2 = [0]
输出:[0]
思路:如何合并两条升序链表??
好难哦 要用溯洄了 溯洄是我最难的搞的。 怎么溯洄呀~
比如有两条链表L1 和 L2
对于L1[0] , L2[0]
如果L1[0] < L2[0]: 则 L1[0] + merge(L1[1], L2[0])
如果L1[0] > L2[0]: 则 L2[0] + merge(L1[0], L2[1])
边界问题:如果有一个链表空了,那就返回l2 。
def mergeTwoLists(l1, l2):
if not l1: return l2
if not l2: return l1
if l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
题目四:输入两个链表,找出它们的第一个公共节点
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
思路是
考虑构建两个节点指针 A , B 分别指向两链表头节点 headA , headB ,做如下操作:
指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 node 时,共走步数为:
a + (b - c)
a+(b−c)
指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 node 时,共走步数为:
b + (a - c)
b+(a−c)
如下式所示,此时指针 A , B 重合,并有两种情况:
a + (b - c) = b + (a - c)
a+(b−c)=b+(a−c)
若两链表 有 公共尾部 (即 c > 0c>0 ) :指针 A , B 同时指向「第一个公共节点」node 。
若两链表 无 公共尾部 (即 c = 0c=0 ) :指针 A , B 同时指向 null。
所以当A = B的时候,即A和B重合的时候,即为第一个公共节点。
def getIntersectionNode(headA,headB):
A,B = headA,headB
while A!= B:
if A: A=A.next
else A = headB
if B: B = B.next
else: B = headA
return A
给定一个链表,判断链表中是否有环
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况
如果链表中存在环,则返回 true 。 否则,返回 false
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
输入:head = [1], pos = -1
输出:false
解释:链表中没有环
方法一: 哈希表
首先,录入所有的元素,如果出现了重复的就返回True,否则是False。
def hasCycle(self, head: ListNode) -> bool:
satck = []
N = len(head)
while head:
if head in stack:
return True
stack.append(head)
head = head.next
时间复杂度是O(N): 最坏的情况是需要遍历所有节点N
空间复杂度都是O(N):这里是哈希表的开销,最坏的情况是每一个节点都收录入哈希表。
方法二:快慢指标
快慢指标是指 慢指标放在head, 快指标放在head.next, 快指标走两步,慢指标走一步。如果链表是有环的话,迟早慢指标和快指标会相遇。
若有环,两指针一定会相遇。因为每走 1 轮,fast 与 slow 的间距 +1,fast 终会追上 slow。
举个例子理解:
输入:head = [3,2,0,-4], pos = 1 即环在2那相连接。
下面展示slow和fast的路径
slow: 3 --> 2 --> 0
fast: 2 --> -4 --> 0
在0节点的时候重合了;
为什么不把slow和fast都放在同一节点开始 这是因为如果开始一样的话就没法进入循环 while slow != fast
def hasCycle(self, head: ListNode) -> bool:
#排除特殊情况
if not head or not head.next: return False
slow = head
fast = head.next
while slow != fast:
#如果fast是None 或者fast.next是None的话 表示有末端-->无环
if not fast or not fast.next: return False
slow = slow.next
fast = fast.next.next
return True
空间复杂度:O(1)。我们只使用了两个指针的额外空间
时间复杂度:O(N)
当链表中不存在环时,快指针将先于慢指针到达链表尾部,链表中每个节点至多被访问两次。
当链表中存在环时,每一轮移动后,快慢指针的距离将减小一。而初始距离为环的长度,因此至多移动 N 轮
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。
说明:不允许修改给定的链表。
进阶:
你是否可以使用 O(1) 空间解决此题?
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
同理方法一:哈希表
class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
hashtable = []
while head:
if head in hashtable:
return head
hashtable.append(head)
head = head.next
但这里的时间复杂度和空间复杂度都是O(N).有没有空间复杂度低的方法呢,那肯定是慢块指针了
方法二:慢块指针
这里复杂了一点是因为需要输出 开始入环的第一个节点。 之前那道题只是输出是否有环。
所以这里的思路是:
假设链表是 a + b形式,a代表环外的节点数,b代表环内的节点数。
假设slow和fast相遇的时候,
必有
fast = 2 * slow 因为fast的步数是slow的两倍,现在是同一起点出发。
为了跟slow重合,fast比slow多跑n个环,也就是多跑nb个步数。
所以
fast = slow + nb
联合两式有:
slow = nb ; fast = 2nb
这个时候,我们想一下,刚好能到入环的节点是 a + bn 个步数。
所以这个时候 从节点出发 a个步数,slow也同时出发a个步数 则就在入环的节点重合
或者说 在这个时候,有一个指针从头开始走,步长为1,跟slow重合肯定是在入环的节点的。
class Solution: def detectCycle(self, head: ListNode) -> ListNode: if not head or not head.next: return slow = head fast = head while True: if not fast or not fast.next: return slow = slow.next fast = fast.next.next if slow == fast: break fast = head while fast != slow: slow = slow.next fast = fast.next return slow
请判断一个链表是否为回文链表
输入: 1->2
输出: false
输入: 1->2->2->1
输出: true
方法一:把链表的va 值依次放入列表。然后通过对比 列表和反转的列表是否一致 来证明回文链表
def isPalindrome(head: ListNode):
val_list = []
cur = head
while cur:
val_list.append(cur.val)
cur = cur.next
return val_list == val_list[::-1]
这里的时间复杂度和空间复杂度是O(N)
方法二:快慢指针
思路是:由于快指针fast 比 慢指针slow 步数的两倍。
所以先
找到前半部分的链表
找到后半部分的链表
再反转后半部们的链表
对比这两个链表是否一致
回复原来的链表。
返回结果
#提取前半部分的链表 def first_half(self,head): fast = head slow = head while True: if not fast or not fast.next: return fast = fast.next.next slow = slow.next if slow == fast: break return slow #反转链表 def reverse_list(self,head): pre,cur = None,head while cur: nxt = cur.next cur.next = pre pre = cur cur = nxt return pre # def isPalindrome(self, head: ListNode) -> bool: if head is None: return True # 找到前半部分链表的尾节点并反转后半部分链表 first_half_end = self.first_half(head) second_half_start = self.reverse_list(first_half_end.next) # 判断是否回文 result = True first_position = head second_position = second_half_start while result and second_position is not None: if first_position.val != second_position.val: result = False first_position = first_position.next second_position = second_position.next return result
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。