面试题5:从尾到头打印链表:从头到尾遍历链表,并用一个栈存储每个结点的值,之后出栈输出值即可
编译器:python3.5.2
'''
输入一个链表,从尾到头打印链表每个节点的值。
'''
class ListNode:
def __init__(self, x=None):
self.val = x
self.next = None
class Solution:
def printListFromTailToHead(self, listNode):
if listNode.val == None:
return
l = []
head = listNode
while head:
l.insert(0, head.val)
head = head.next
return l
node1 = ListNode(10)
node2 = ListNode(11)
node3 = ListNode(13)
node1.next = node2
node2.next = node3
singleNode = ListNode(12)
test = ListNode()
S = Solution()
print(S.printListFromTailToHead(node1))
print(S.printListFromTailToHead(test))
print(S.printListFromTailToHead(singleNode))
面试题13:在O(1)时间删除链表结点:当要删除的结点不是尾结点而且不是仅有一个结点的头结点,可以把该结点i的下一个结点j的内容复制到结点i,同时把i结点的next指向j结点的next,然后再删除结点j。如果要删除的链表为单结点链表且待删除的结点就是头结点,需要把头结点置为None,如果删除的结点为链表的尾结点,那么就需要顺序遍历链表,找到尾节点前面一个结点,然后将其next置空。
编译器:python3.5.2
编程环境:pycharm2018.1.2x64
'''
给定单向链表的头指针和一个结点指针,定义一个函数在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__()
node1 = ListNode(10)
node2 = ListNode(11)
node3 = ListNode(13)
node4 = ListNode(15)
node1.next = node2
node2.next = node3
node3.next = node4
S = Solution()
S.DeleteNode(node1, node3)
print(node3.val)
S.DeleteNode(node1, node3)
print(node3.val)
print(node2.val)
S.DeleteNode(node1, node1)
print(node1.val)
S.DeleteNode(node1, node1)
print(node1.val)
面试题15:链表中倒数第k个结点:代码的鲁棒性。需要注意:如果输入的链表为空;k大于链表的长度;k为0的情况。对于正常情况,设置两个指针分别指向头结点,第一个指针向前走k-1步,走到正数第k个结点,同时保持第二个指针不动,然后第一个指针和第二个指针每次同时前移一步,这样第一个指针指向尾结点的时候,第二个指针指向倒数第k个结点。判断尾结点的条件是 pNode.next == None。
编译器:python3.5.2
编程环境:pycharm2018.1.2x64
'''
输入一个链表,输出该链表中倒数第k个结点。
'''
'''
这道题的思路很好
如果在只希望一次遍历的情况下, 寻找倒数第k个结点, 可以设置两个指针
第一个指针先往前走k-1步, 然后从第k步开始第二个指针指向头结点
然后两个指针一起遍历
当地一个指针指向尾节点的时候, 第二个指针正好指向倒数第k个结点
推广: 寻找中间节点, 两个指针一起, 第一个指针每次走两步, 第二个指针每次走一步, 快指针指到尾部, 慢指针正好指到中间
'''
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def FindKthToTail(self, head, k):
if head == None or k <= 0:
return None
pAHead = head
pBehind = None
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
node1 = ListNode(10)
node2 = ListNode(11)
node3 = ListNode(13)
node1.next = node2
node2.next = node3
S = Solution()
print(S.FindKthToTail(node1, 3).val)
面试题16:反转链表:需要注意三个问题:1、输入的链表头指针为None;2、整个链表只有一个结点时 ;3、反转后的链表出现断裂,返回的翻转之后的头节点不是原始链表的尾结点。因此需要引入一个翻转后的头结点,以及一个指向当前结点的指针,一个指向当前结点前一个结点的指针,一个指向当前结点后一个结点的指针,防止出现断裂。推广:递归实现反转链表
编译器:python3.5.2
编程环境:pycharm2018.1.2x64
'''
反转链表
输入一个链表,反转链表后,输出链表的所有元素
'''
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
pReverseHead = None
pNode = pHead
pPrev = None
while pNode != None:
pNext = pNode.next
if pNext == None:
pReverseHead = pNode
pNode.next = pPrev
pPrev = pNode
pNode = pNext
return pReverseHead
# 递归实现反转链表
def ReverseListRec(self, pHead):
if not pHead or not pHead.next:
return pHead
else:
pReverseHead = self.ReverseList(pHead.next)
pHead.next.next = pHead
pHead.next = None
return pReverseHead
node1 = ListNode(10)
node2 = ListNode(11)
node3 = ListNode(13)
node1.next = node2
node2.next = node3
S = Solution()
p = S.ReverseListRec(node1)
print(p.val)
面试题17:合并两个排序的列表:要注意特殊输入,如果输入是空链表,不能崩溃。
编译器:python3.5.2
编程环境:pycharm2018.1.2x64
'''
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
'''
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
if pHead1 == None:
return pHead2
elif 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
node1 = ListNode(1)
node2 = ListNode(3)
node3 = ListNode(5)
node1.next = node2
node2.next = node3
node4 = ListNode(2)
node5 = ListNode(4)
node6 = ListNode(6)
node4.next = node5
node5.next = node6
S = Solution()
S.Merge(node1, node4)
print(node4.val)
面试题37:两个链表的第一个公共结点:首先依次遍历两个链表,记录两个链表的长度m和n,如果 m > n,那么我们就先让长度为m的链表走m-n个结点,然后两个链表同时遍历,当遍历到相同的结点的时候停止即可。对于 m < n,同理。
编译器:python3.5.2
编程环境:pycharm2018.1.2x64
'''
输入两个链表,找出它们的第一个公共结点。
'''
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
nLength1 = self.GetListLength(pHead1)
nLength2 = self.GetListLength(pHead2)
nLengthDiff = abs(nLength1 - nLength2)
if nLength1 > nLength2:
pListHeadLong = pHead1
pListHeadShort = pHead2
else:
pListHeadLong = pHead2
pListHeadShort = pHead1
for i in range(nLengthDiff):
pListHeadLong = pListHeadLong.next
while pListHeadLong != None and pListHeadShort != None and pListHeadLong != pListHeadShort:
pListHeadLong = pListHeadLong.next
pListHeadShort = pListHeadShort.next
pFirstCommonNode = pListHeadLong
return pFirstCommonNode
def GetListLength(self, pHead):
nLength = 0
while pHead != None:
pHead = pHead.next
nLength += 1
return nLength
面试题56:链表中环的入口结点:寻找链表中环的入口结点主要分成三个步骤:首先是设置两个快慢指针,如果快慢指针相遇,则快慢指针必然都在环中;然后从相遇的地方设置一个指针向后遍历并记录走的步数,当这个指针重新指到开始的位置的时候,当前对应的步数就是环中结点的数量k;然后设置两个指针从链表开始,第一个节点先走k步,然后第二个指针指到链表的开始,两个指针每次都向后走一步,两个指针相遇的位置就是链表的入口。
编译器:python3.5.2
编程环境:pycharm2018.1.2x64
'''
一个链表中包含环,请找出该链表的环的入口结点。
'''
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def MeetingNode(self, pHead):
if pHead == None:
return None
pSlow = pHead.next
if pSlow == None:
return None
pFast = pSlow.next
while pFast:
if pSlow == pFast:
return pSlow
pSlow = pSlow.next
pFast = pFast.next
if pFast:
pFast = pFast.next
def EntryNodeOfLoop(self, pHead):
meetingNode = self.MeetingNode(pHead)
if not meetingNode:
return None
NodeLoop = 1
flagNode = meetingNode
while flagNode.next != meetingNode:
NodeLoop += 1
flagNode = flagNode.next
pFast = pHead
for i in range(NodeLoop):
pFast = pFast.next
pSlow = pHead
while pFast != pSlow:
pFast = pFast.next
pSlow = pSlow.next
return pFast
node1 = ListNode(1)
node2 = ListNode(2)
node3 = ListNode(3)
node4 = ListNode(4)
node5 = ListNode(5)
node6 = ListNode(6)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
node5.next = node6
node6.next = node3
s = Solution()
print(s.EntryNodeOfLoop(node1).val)
面试题57:删除链表中重复的结点:我们需要设置一个指针preNode,preNode最开始为None,然后设置两个指针,pNode指向当前节点,pNext指向pNode下一个结点:
如果pNext不为空而且pNext的值等于pNode的值,那么就说明出现了重复数字的结点,就需要删除,然后从pNode开始遍历,如果结点值等于前面那个重复值,继续遍历。当遍历到None或者不同值结点的时候,这时候需要判断preNode结点,如果preNode结点为None,就说明我们刚才的重复结点是从整个链表的头结点开始重复的,就直接把pHead设置为当前结点,pNode也设置为当前结点。反之,如果preNode不为None,直接把preNode的下一个指针指向当前节点,pNode指向preNode即可;
如果pNext为空或者pNext的值不等于pNode的值,说明当前的这个pNode和后面的值不重复,直接令preNode = pNode,pNode指向下一个结点即可。
编译器:python3.5.2
编程环境:pycharm2018.1.2x64
'''
删除链表中重复的结点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
'''
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def deleteDuplication(self, pHead):
if pHead == None:
return
preHead = None
pNode = pHead
while pNode != None:
needDelete = False
nextNode = pNode.next
if nextNode != None and nextNode.val == pNode.val:
needDelete = True
if needDelete == False:
preHead = pNode
pNode = pNode.next
else:
nodeVal = pNode.val
pToBeDel = pNode
while pToBeDel != None and pToBeDel.val == nodeVal:
pToBeDel = pToBeDel.next
if preHead == None:
pHead = pToBeDel
pNode = pToBeDel
continue
else:
preHead.next = pToBeDel
pNode = preHead
return pHead
node1 = ListNode(1)
node2 = ListNode(2)
node3 = ListNode(3)
node4 = ListNode(3)
node5 = ListNode(4)
node6 = ListNode(4)
node7 = ListNode(5)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
node5.next = node6
node6.next = node7
s = Solution()
print(s.deleteDuplication(node1).val)
class Solution:
def deleteDuplication(self, pHead):
# write code here
pos = pHead
ret = ListNode(-1)
tmp = ret
flag = False
while(pos and pos.next):
if pos.val == pos.next.val:
flag = True
pos.next = pos.next.next
else:
if flag:
flag = False
else:
tmp.next = ListNode(pos.val)
tmp = tmp.next
pos = pos.next
if pos and flag==False:
tmp.next = ListNode(pos.val)
return ret.next