剑指offer---- 面试题6: 从尾到头打印链表
题目描述
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
li=[]
while listNode:
li.insert(0,listNode.val)
listNode=listNode.next
return li
剑指offer---- 面试题18: 删除链表中重复的结点
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5。
'''
法一思路:
1.新建一个节点n,连接并作为pHead的头节点(防止开始两个节点元素就相等)
2.pre指向n,cur指向pHead
3.循环判断cur.val==cur.next.val:
如果==,创建游标tmp指向cur.next,循环判断直到tmp.val!=cur.val,则pre.next=tmp
如果!=,pre=cur,cur=cur.next
4.返回n.next
'''
# -*- coding:utf-8 -*-
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def deleteDuplication(self, pHead):
# write code here
n=ListNode(0)
n.next=pHead
pre=n
cur=pHead
while cur:
if cur.next and cur.next.val == cur.val:
tmp=cur.next
while tmp and tmp.val == cur.val:
tmp=tmp.next
pre.next=tmp
cur=tmp
else:
pre=cur
cur=cur.next
return n.next
'''
法二思路:
1.先把链表所有值放到列表里面,去重
2.新建一个头节点
3.将列表每一个元素变为一个节点,连接到新建头节点后面
4.返回头节点后的链表
'''
# -*- coding:utf-8 -*-
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def deleteDuplication(self, pHead):
# write code here
res=[]
while pHead:
res.append(pHead.val)
pHead=pHead.next
res=list(filter(lambda c :res.count(c)==1,res))
tmp=ListNode(0)
pre =tmp
for i in res:
node=ListNode(i)
pre.next=node
pre=pre.next
return tmp.next
'''
## lambda语句
lambda语句中,冒号前是参数,可以有多个,用逗号隔开,冒号右边的返回值。lambda语句构建的其实是一个函数对象,见证一下:
foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
print filter(lambda x: x % 3 == 0, foo)
[18, 9, 24, 12, 27]
print map(lambda x: x * 2 + 10, foo)
[14, 46, 28, 54, 44, 58, 26, 34, 64]
print reduce(lambda x, y: x + y, foo)
139
'''
剑指offer---- 面试题22. 链表中倒数第k个结点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
'''
思路:
2个游标,p1,p2,p2先走k-1步,然后p1 p2一起走,当p2走到尾时,p1就是链表的倒数第k个节点
注意:
最后要返回p1,而不是p1.val,因为题目要求返回节点而不是返回值。
'''
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindKthToTail(self, head, k):
# write code here
if head==None or k<1:
return None
p2=head
p1=head
while k>1:
if p2.next!=None:
p2=p2.next
k-=1
else:
return None
while p2.next!=None:
p1=p1.next
p2=p2.next
return p1
剑指offer---- 面试题23. 链表中环的入口结点
题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路
p1,p2同时指向开始,p1每次走一步,p2每次走两步,通过下面的数学计算,当p1p2相遇时(p2环内走过n圈了),m=s,即当相遇时,p1p2每次都走一步,直到相遇即为环口的位置。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
if pHead==None or pHead.next==None:
return None
p1=pHead
p2=pHead
while p2 and p2.next:
p1=p1.next
p2=p2.next.next
if p1==p2:
p1=pHead
while p1 !=p2:
p1=p1.next
p2=p2.next
return p1
return None
剑指offer---- 面试题24. 反转链表
题目描述
输入一个链表,反转链表后,输出新链表的表头。
'''
思路:
三个游标,让链表箭头指向反转,即cur.next=pre,始终让cur指向前一个节点,然后后移三个游标。
'''
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
if pHead==None or pHead.next==None:
return pHead
pre = None
cur = pHead
while cur != None:
tmp=cur.next
cur.next=pre
pre=cur
cur=tmp
return pre
剑指offer---- 面试题25. 合并两个排序的链表
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
'''
法一思路:
把两个链表的值都放在一个列表里,排序,在编程一个一个的节点连成一个链表。
'''
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
res=[]
while pHead1:
res.append(pHead1.val)
pHead1=pHead1.next
while pHead2:
res.append(pHead2.val)
pHead2=pHead2.next
res.sort()
tmp=ListNode(0)
pre=tmp
for i in res:
node=ListNode(i)
pre.next=node
pre=pre.next
return tmp.next
'''
法二思路:(推荐)
递归:
游标指向空,比较两个链表首届点的值,谁小,游标=谁,然后递归循环剩下的,
注意,最后两个链表肯定有一个剩下最后一个节点,直接返回连到链表上即可
'''
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
if pHead1==None:
return pHead2
if pHead2==None:
return pHead1
pMergeHead=None
if pHead1.val<pHead2.val:
pMergeHead=pHead1
pMergeHead.next=self.Merge(pHead1.next, pHead2)
else:
pMergeHead=pHead2
pMergeHead.next=self.Merge(pHead1, pHead2.next)
return pMergeHead
'''
法三思路:
循环执行法二思想,游标指向一个构造的节点,
'''
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
res=pMergeHead=ListNode(0) #这里我之前写的pMergeHead=ListNode(0) ,return pMergeHead.next就不对,因为在循环结束跳出循环后pMergeHead.next=pHead1 or pHead2,return pMergeHead.next就直接返回pHead1 or pHead2了
while pHead1 and pHead2:
if pHead1.val<pHead2.val:
pMergeHead.next=pHead1
pHead1=pHead1.next
else:
pMergeHead.next=pHead2
pHead2=pHead2.next
pMergeHead=pMergeHead.next
pMergeHead.next=pHead1 or pHead2
return res.next
剑指offer---- 面试题35. 复杂链表的复制
题目描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
原复杂链表用笨办法复制的话,randomListNode在复制的时候,都要一个一个找,那么每一个都要找n次,时间复杂度就是O(n²)
原复杂链表:
在原链表中复制节点,并指定新建节点的random指向,通过A.next.random=a.random.next实现。
最后断开node和新建node的连接
'''
法一:
1.复制每个节点,并插入原节点后面
2.指定每个新node的random方向,注意有A.next.next出现时,要保证A.next存在,否则报错
3.断开原node何新node之间的连接,返回头部,注意:这里了应该有三个游标,其他两个最后指向了链表末尾,第三个用来返回头部
'''
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
if pHead==None:
return None
#1.复制每个节点,并插入原节点后面
pTmp=pHead
while pTmp:
node =RandomListNode(pTmp.label)
node.next=pTmp.next
pTmp.next=node
pTmp=node.next
#2.指定每个新node的random方向
pTmp=pHead
while pTmp:
if pTmp.random:
pTmp.next.random=pTmp.random.next
pTmp=pTmp.next.next
#3.断开原node何新node之间的连接
pTmp=pHead
NewHead=pHead.next
pNewHead=pHead.next
while pTmp:
pTmp.next=pTmp.next.next
if pNewHead.next:
pNewHead.next=pNewHead.next.next
pNewHead=pNewHead.next
pTmp=pTmp.next
return NewHead
'''
法二:
直接用python的深拷贝,一步
竟然可以通过牛客!!!
'''
# -*- coding:utf-8 -*-
# class RandomListNode:
# def __init__(self, x):
# self.label = x
# self.next = None
# self.random = None
import copy
class Solution:
# 返回 RandomListNode
def Clone(self, pHead):
# write code here
res=copy.deepcopy(pHead)
return res
剑指offer---- 面试题52. 两个链表的第一个公共结点
题目描述
输入两个链表,找出它们的第一个公共结点。
思路
1.两个链表的游标从头开始一起走,
2.当短的链表next为None时,计数长链表剩下的节点数k,长链表先走k步,然后循环长短链表一起走,循环条件为长短链表节点相等,返回短(长)链表节点。
2是一个封装函数