赞
踩
1、从链表的末尾添加节点
2、删除链表节点
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该节点
如果用头指针开始遍历链表时间复杂度为O(n),要在O(1)的时间删除,需要得到被删除的结点的前一个结点,但是前一个结点很难获得,但是我们可以很方便的得到要删除的结点的下一个结点,如果我们把下一个结点的内容复制到需要删除的结点上覆盖原有的内容,在把下一个结点删除。
代码实现:
class ListNode:
def __init__(self, x=None):
self.val = x
self.next = None
def __del__(self):
self.val = None
self.next = None
class Solution:
def DeleteNode(self, pListHead, pToBeDeleted):
if not pListHead or not pToBeDeleted:
return None
if pToBeDeleted.next != None:
pNext = pToBeDeleted.next
pToBeDeleted.val = pNext.val
pToBeDeleted.next = pNext.next
pNext.__del__()
elif pListHead == pToBeDeleted:
pToBeDeleted.__del__()
pListHead.__del__()
else:
pNode = pListHead
while pNode.next != pToBeDeleted:
pNode = pNode.next
pNode.next = None
pToBeDeleted.__del__()
3、链表中倒数第K个节点
输入一个链表,输出该链表中倒数第K个结点。
为了实现只遍历一遍链表就能找到倒数第K个结点,我们可以定义两个指针,第一个指针从链表的头指针开始遍历向前走k-1,第二个指针保持不动;从第K步开始,第二个指针也开始从链表的头指针开始遍历。由于两个指针的距离保持在k-1,当第一个指针到达链表的尾节点时,第二个指针正好是倒数第K个结点。
代码实现:
def FindKthToTail(self, head, k):
# write code here
pAhead = ListNode(0)
pAhead = head
pBehind = ListNode(0)
if head == None:
return
if k == 0:
return
for i in range(k - 1):
if pAhead.next != None:
pAhead = pAhead.next
else:
return None
pBehind = head
while (pAhead.next != None):
pAhead = pAhead.next
pBehind = pBehind.next
return pBehind
扩展问题
1 求链表的中间节点。
这个问题可以定义两个指针。同时从链表的头结点出发,一个指针一次走一步,另一个指针一次走两步。
当走的快的指针走到链表的末尾时,走得慢的指针正好在链表的中间
class Solution1:
def middlenode(self,node):
phead = ListNode(0)
pnext = ListNode(0)
phead = node
pnext = phead
if phead is None and pnext is None:
return
while pnext.next!= None:
phead = phead.next
pnext = pnext.next.next
if pnext.next == None:
result = phead.val
return result
4、反转链表
定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。
为了防止链表断开,我们需要维护三个指针,分别指向当前遍历结点、它的前一个结点以及后一个结点。
反转链表的操作为当前结点的下一个结点指向前一个结点所指的结点。
代码实现:
def ReverseList(self, pHead):
# write code here
preNode = None
pReverseNode = None
pNode = pHead
while(pNode != None):
pNext = ListNode(0)
pNext = pNode.next
if pNext == None:
pReverseNode = pNode
pNode.next = preNode
preNode = pNode
pNode = pNext
return pReverseNode
5、从尾到头打印链表
从尾到头来打印,相当于“先进后出”,借助栈的数据结构。
class listnode:
def __init__(self,val):
self.val = val
self.next = None
def printlist(listnode):
stack = []
while listnode is not None:
stack.append(listnode.val)
listnode = listnode.next
for i in range(len(stack)-1,-1,-1):
print(stack[i])
6、合并两个排序的链表
输入两个递增排序的链表,合并两个链表并使新链表中的结点任然是按照递增排序;
对两个链表中的元素进行对比,用一个新的链表记录两个链表中的较小的值,然后增加到新链表中,直到两个链表遍历完成。
代码实现:
def merge(self,Phead1,Phead2):
if Phead1 == None:
return Phead2
elif Phead2 == None:
return Phead1
pmerge = ListNode(0)
if Phead1.val < Phead2.val:
pmerge = Phead1
pmerge.next = self.merge(Phead1.next,Phead2)
else:
pmerge = Phead2
pmerge.next = self.merge(Phead1,Phead2.next)
return pmerge
7、两个链表的第一个公共节点
如果两个链表有公共结点,那么公共结点出现在两个链表的尾部。如果我们从两个链表的尾部开始往前比较,最后一个相同的结点就是我们要找的结点。
于是我们借助栈,分别把两个链表的结点放入两个栈中,这样两个链表的尾节点就位于两个栈的栈顶,接下来比较两个栈顶的结点是否相同。如果相同,则把栈顶弹出接着比较下一个栈顶,知道找到最后一个相同的结点。
更加简单的方法:
受限遍历两个链表得到它们的长度,就能知道那个链表比较长,以及长的链表比短的链表多几个结点。在第二次遍历的时候,在较长的链表上先走若干步,接着再同步在两个链表上遍历,找到的第一个相同的结点就是它们的第一个公共结点。
代码实现:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
lenhead1 =0
lenhead2 =0
p1 = pHead1
p2 = pHead2
while pHead1.next !=None:
lenhead1 +=1
pHead1= pHead1.next
while pHead2.next !=None:
lenhead2 +=1
pHead2 = pHead2.next
if lenhead2 > lenhead1:
step = lenhead2 -lenhead1
for i in range(step):
if p2 != None:
p2 = p2.next
while p2 != None and p2!=None:
if p1.val == p2.val:
return p1.val
break
else:
p2 = p2.next
p1 = p1.next
else:
step = lenhead1 - lenhead2
for i in range(step):
if p1 != None:
p1 = p1.next
while p2 != None and p1 != None:
if p1.val == p2.val:
return p1.val
break
else:
p2 = p2.next
p1 = p1.next
8、判断两个链表是否有环相关问题
定义两个指针,同时从链表的头结点出发,一个指针一次走一步,另一个指针一次走两步。如果走得快的指针追上了走的慢的指针,那么链表就是环形链表;
代码实现:
def findlink(self,node):
phead = ListNode(0)
pnext = ListNode(0)
phead = node
pnext = phead
if phead is None and pnext is None:
return
phead = phead.next
pnext = pnext.next.next
while phead.val != pnext.val and pnext.next != None:
phead = phead.next
pnext = pnext.next.next
if phead.val == pnext.val:
return True
break
else:
return False
9、删除链表中重复的结点
10、复杂链表的复制
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。