一、简单操作
1、输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
class Solution:
def printListFromTailToHead(self, listNode):
res=[]
while listNode:
res.insert(0,listNode.val)
listNode=listNode.next
return res
准备工作:输出一个链表,怎么码代码?输出链表1->2->3
class ListNode:
def __init__(self,x):
self.val=x
self.next=None
def PrintChain(node):
while node:
print node.val
node=node.next
l1=ListNode(1)
l2=ListNode(2)
l3=ListNode(3)
l1.next=l2
l2.next=l3
PrintChain(l1)
2、输入一个链表,输出该链表中倒数第k个结点。
class Solution:
def FindKthToTail(self,head,k):
firstPoint=head
secondPoint=head
for i in range(k):
if firstPoint==None:
return None
firstPoint=firstPoint.next
while firstPoint!=None:
firstPoint=firstPoint.next
secondPoint=secondPoint.next
return secondPoint
3、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
class Solution:
def Merge(self, pHead1, pHead2):
if pHead1==None:
return pHead2
elif pHead2==None:
return pHead1
if pHead1.val<pHead2.val:
newHead=pHead1
pHead1=pHead1.next
else:
newHead=pHead2
pHead2=pHead2.next
newHead.next=self.Merge(pHead1,pHead2)
return newHead
二、反转链表(或反转其中一部分)与其应用
反转链表;leetcode206. Reverse Linked List
class Solution:
def ReverseList(self, pHead):
pTmp = pHead
newHead = None
while pTmp:
pTmp1 = pTmp.next
pTmp.next = newHead
newHead = pTmp
pTmp = pTmp1
return newHead
或,思想一样
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
if pHead == None:
return None
pTmp = pHead
pTmp1 = pHead.next
newHead = None
while pTmp:
pTmp.next = newHead
newHead = pTmp
pTmp = pTmp1
if pTmp1:
pTmp1 = pTmp1.next
return newHead
leetcode92. Reverse Linked List II对链表中一部分进行反向
class Solution:
def reverseBetween(self, head, m, n):
dummy = ListNode(0) #重点:必须加一个虚拟的指针
dummy.next = head
p1 = dummy
for i in range(m-1):
p1 = p1.next
p2 = p1.next
newhead = None
for i in range(n-m+1): #反转m到n链表
p3 = p2.next
p2.next = newhead
newhead = p2
p2 = p3
p1.next.next = p2
p1.next = newhead
return newhead if p1 == dummy else head
letcode25. Reverse Nodes in k-Group
class Solution:
def reverseKGroup(self, head, k):
i = 0
p = head
p1 = head
while p and i<k:
p = p.next
i += 1
if i < k: #判断够不够k个
return head
pre = self.reverseKGroup(p,k) #若够k则处理下一段
for i in range(k): #对这一段进行翻转
p2 = p1.next
p1.next = pre
pre = p1
p1 = p2
return pre
leetcode234. Palindrome Linked List 1->2->2->1 True
#先用快慢指针找到中间位置,若不要求空间O(1),则可用栈依次放入前半截元素,再一一取出与
#后边链中元素比对;要求空间O(1):将后半截链表反转,再与前半截一一比对
class Solution:
def isPalindrome(self, head):
fastp = slowp = head #快慢指针找中间位置
while fastp and fastp.next and slowp:
fastp = fastp.next.next
slowp = slowp.next
newhead = None
while slowp: #反转后半截链表,设置新表头newhead
p1 = slowp.next
slowp.next = newhead
newhead = slowp
slowp = p1
while newhead and head.val == newhead.val: #一一比对
head = head.next
newhead = newhead.next
if newhead == None:
return True
else:
return False
三、判断链表里是否有环
leetcode141. Linked List Cycle判断是否有环
class Solution(object):
def hasCycle(self, head):
fastp = slowp = head
while fastp and fastp.next:
fastp = fastp.next.next
slowp = slowp.next
if fastp == slowp:
return True
return False
leetcode142. Linked List Cycle II,剑指offer链表中环的入口节点:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
#设从起点到环的起点长度为a,从环的起点到第一次相遇长度为b,圈长为n
# 根据2*(a+b)=a+b+k*n,得a+b=k*n。所以本题用快慢指针,待第一次相遇
#再重置慢指针到起点,两个指针同步走,再次相聚即是环的入口,因为a+b是
# n的整数倍
class Solution(object):
def detectCycle(self, head):
fastp = slowp = head
while fastp and fastp.next:
fastp = fastp.next.next
slowp = slowp.next
if fastp == slowp:
slowp = head
break
if fastp == None or fastp.next == None:
return None
else:
while slowp != fastp:
fastp = fastp.next
slowp = slowp.next
return slowp
class Solution:
def EntryNodeOfLoop(self, pHead):
fastp = slowp = pHead
while fastp and fastp.next:
fastp = fastp.next.next
slowp = slowp.next
if fastp == slowp:
slowp = pHead
break
if fastp == None or fastp.next == None:
return None
else:
while slowp != fastp:
fastp = fastp.next
slowp = slowp.next
return slowp
四、单向链表找交点
160. Intersection of Two Linked Lists输入两个链表,找出它们的第一个公共结点。
法一:
#将长的链先往后next,直到两个链长度相等,再同时next,直到两个相等
class Solution(object):
def getIntersectionNode(self, headA, headB):
lenA = lenB = 0 #先得A链长度lenA和B链长度lenB
pA = headA
pB = headB
while pA:
pA = pA.next
lenA += 1
while pB:
pB = pB.next
lenB += 1
pA = headA
pB = headB
while lenA > lenB: #将长链next直到两链相等
pA = pA.next
lenA -= 1
while lenB > lenA:
pB = pB.next
lenB -= 1
while pA != pB:
pA = pA.next
pB = pB.next
return pA
以下是剑指offer相应题目代码
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
pTmp1=pHead1
pTmp2 = pHead2
while pTmp1 and pTmp2:
pTmp1=pTmp1.next
pTmp2=pTmp2.next
if pTmp1:
k = 0
while pTmp1:
pTmp1 = pTmp1.next
k += 1
pTmp1=pHead1
pTmp2=pHead2
for i in range(k):
pTmp1=pTmp1.next
else:
k=0
while pTmp2:
pTmp2 = pTmp2.next
k += 1
pTmp2=pHead2
pTmp1=pHead1
for i in range(k):
pTmp2=pTmp2.next
while pTmp1 != pTmp2:
pTmp1=pTmp1.next
pTmp2=pTmp2.next
return pTmp1
法二:通过调用函数,将两种情况调用
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
pTmp1 = pHead1
pTmp2 = pHead2
while pTmp1 and pTmp2:
pTmp1 = pTmp1.next
pTmp2 = pTmp2.next
def findequal(longchain,shortchain, longhead, shorthead):
k=0
while longchain:
longchain=longchain.next
k += 1
longchain = longhead
shortchain = shorthead
for i in range(k):
longchain=longchain.next
while longchain != shortchain:
longchain=longchain.next
shortchain=shortchain.next
return longchain
if pTmp1:
return findequal(pTmp1,pTmp2,pHead1,pHead2)
else:
return findequal(pTmp2,pTmp1,pHead2,pHead1)
五、复值random指针
leetcode138. Copy List with Random Pointer
class Solution(object):
def copyRandomList(self, head):
if head == None:
return None
p = head
while p: #复值每一个节点加到原节点后面
node = Node(p.val, p.next, p.random)
node.next = p.next
p.next = node
p = node.next
p = head
while p: #将random指针复值
if p.random:
p.next.random = p.random.next
p = p.next.next
p = head
newhead = p.next
p1 = newhead
while p and p1.next: #将两条链断开
p.next = p1.next
p = p.next
p1.next = p.next
p1 = p1.next
p.next = None
p1.next = None
return newhead
对应剑指offer题目:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
方法一:
import copy
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
ret=copy.deepcopy(pHead)
return ret
方法二:
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
if pHead == None:
return None
pTmp = pHead
while pTmp:
node = RandomListNode(pTmp.label)
node.next = pTmp.next
pTmp.next = node
pTmp = node.next
pTmp = pHead
while pTmp:
if pTmp.random:
pTmp.next.random = pTmp.random.next
pTmp = pTmp.next.next
pTmp = pHead
pTmp1 = pHead.next
newhead = pHead.next
while pTmp:
pTmp.next = pTmp.next.next
pTmp=pTmp.next
if pTmp1.next:
pTmp1.next = pTmp1.next.next
pTmp1=pTmp1.next
return newhead
注:若想在pycharm调试则需加
if __name__ == "__main__":
n1=RandomListNode(1)
n2 = RandomListNode(2)
n3 = RandomListNode(3)
n4 = RandomListNode(4)
n1.next = n2
n2.next = n3
n3.next = n4
s=Solution()
newhead = s.Clone(n1)
tmp = newhead
while tmp:
print tmp.label
tmp = tmp.next
**六、链表partition **
leetcode86. Partition List:链表里存放整数,给定x,把比x小的节点放到>=x之前
#思路:建立两个虚拟表头,比x小的放到leftp后边,其他放到rightp后边,最后连到一起
class Solution:
def partition(self, head, x):
dummyleft = ListNode(0)
dummyright = ListNode(0)
leftp = dummyleft
rightp = dummyright
p = head
while p:
if p.val < x:
leftp.next = p
leftp = leftp.next
else:
rightp.next = p
rightp = rightp.next
p = p.next
rightp.next = None
leftp.next = dummyright.next
return dummyleft.next