1、(JZ16)合并两个排序的链表
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
非递归做法:
# -*- 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
tmp = ListNode(0)
pHead = tmp
while pHead1 and pHead2:
if pHead1.val < pHead2.val:
tmp.next = pHead1
pHead1 = pHead1.next
else:
tmp.next = pHead2
pHead2 = pHead2.next
tmp = tmp.next
if not pHead1:
tmp.next = pHead2
if not pHead2:
tmp.next = pHead1
return pHead.next
递归做法:
# -*- 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
if not pHead1: return pHead2
if not pHead2: return pHead1
if pHead1.val<pHead2.val:
pHead1.next = self.Merge(pHead1.next, pHead2)
return pHead1
else:
pHead2.next = self.Merge(pHead1,pHead2.next)
return pHead2
2、(JZ14)链表中倒数第k个节点
输入一个链表,输出该链表中倒数第k个结点。
憨憨做法
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param pHead ListNode类
# @param k int整型
# @return ListNode类
#
class Solution:
def FindKthToTail(self , pHead , k ):
# write code here
if not pHead:
return pHead
tmp = pHead
count = 0
while(tmp):
count += 1
tmp = tmp.next
num = count - k + 1
count = 1
tmp = pHead
if num <= 0:
return None
while(count != num):
count += 1
tmp = tmp.next
return tmp
放入list中,根据list
class Solution:
def FindKthToTail(self , pHead , k ):
# write code here
result = []
if pHead is None:
return None
while pHead:
result.append(pHead)
pHead = pHead.next
if k<1 or k>len(result):
return None
else:
return result[-k]
3、(JZ15)反转链表
输入一个链表,反转链表后,输出新链表的表头。
方法一:储存所有node,再构造链表
方法二:调整指针
pre 指向已调整好链表的最后一个节点
cur 指向待反转链表的第一个节点
tmp 用于保存待反转链表,所以指向待反转链表的第二个节点
# -*- 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 not pHead or not pHead.next:
return pHead
pre = None
cur = pHead
while(cur):
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
5、(JZ36)两个链表的第一个公共节点
输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
写起来简单,但是时间复杂度较高。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
p1,p2 = pHead1,pHead2
while(p1!=p2):
p1 = (pHead2 if p1==None else p1.next)
p2 = (pHead1 if p2==None else p2.next)
return p1
下面这个做法仅比较value,我认为存在问题,但是在解释器中可以通过
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
p1 = pHead1
a = []
while p1:
a.append(p1.val)
p1 = p1.next
p2 = pHead2
while p2:
if p2.val in a:
return p2
p2 = p2.next
6、(JZ55)链表中环的入口节点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
借助list完成。
# -*- 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 not pHead or not pHead.next:
return None
ans = []
p = pHead
while p:
if p not in ans:
ans.append(p)
else:
return p
p = p.next
return None
双指针(快慢)
若不用辅助结构set,该怎么做呢?这里画了一张图
- 初始化:快指针fast指向头结点, 慢指针slow指向头结点
- 让fast一次走两步, slow一次走一步,第一次相遇在C处,停止
- 然后让fast指向头结点,slow原地不动,让后fast,slow每次走一步,当再次相遇,就是入口结点。
如上解释:
如果慢指针slow第一次走到了B点处,距离C点处还有距离Y,那么fast指针应该停留在D点处,且BD距离为Y(图中所示是假设快指针走了一圈就相遇,为了便于分析),
也就是DB+BC=2Y,(因为fast一次走2步,慢指针一次走1步,并且相遇在C处)
在C点处,此时慢指针slow走的点为ABC,距离为X+Y,而快指针fast走的点为ABCDBC,距离为2X+2Y,
又因为:AB=X,BC=Y,快指针走了2次BC,所以CDB距离为X,而AB距离也为X。关键在于AB=CDB
# -*- 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 not pHead:
return None
slow = pHead
fast = pHead
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
if slow==fast:
p_new = pHead
while p_new != slow:
p_new = p_new.next
slow = slow.next
return p_new
return None
7、(JZ3)从尾到头打印链表
递归做法
# -*- 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
if listNode is None:
return []
return self.printListFromTailToHead(listNode.next)+[listNode.val]
读取链表的值,然后反转
# -*- 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
ans = []
if not listNode:
return []
p = listNode
while p!=None:
ans.append(p.val)
p = p.next
return list(reversed(ans))
反转链表
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
pre, cur = None, listNode
while cur !=None:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
ans = []
while pre:
ans.append(pre.val)
pre = pre.next
return ans
8、(JZ25)复杂链表的复制
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
递归作法:
# -*- 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 not pHead:
return None
newnode = RandomListNode(pHead.label)
newnode.random = pHead.random
newnode.next = self.Clone(pHead.next)
return newnode
9、(JZ56)删除链表中重复的结点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteDuplication(self, pHead):
# write code here
if not pHead or not pHead.next:
return pHead
if pHead.val == pHead.next.val:
while pHead.next and pHead.val == pHead.next.val:
pHead = pHead.next
return self.deleteDuplication(pHead.next)
else:
pHead.next = self.deleteDuplication(pHead.next)
return pHead