题目描述(难度:中等)
找出单链表中的倒数第 k 个元素,例如给定单链表:1->2->3->4->5->6->7,则单链表的倒数第 k=3 个元素为 5。(来源:微软)
单链表结构
class LNode:
def __init__(self):
self.data = None # 数据域
self.next = None # 指针域
- 由于单链表中每个结点的地址都存储在其前驱结点的指针域中,因此,对单链表中任何一个结点的访问只能从链表的头指针开始进行遍历。
- 注意:在修改结点指针域的时候,记录下后继结点的地址,否则会丢失后继结点。
方法一:快慢指针
# 构造一个单链表
def ConstructList():
i = 1
head = LNode()
head.next = None
cur = head
# 构造第一个链表
link = [1, 2, 3, 4, 5, 6, 7]
for i in link:
tmp = LNode()
tmp.data = i
tmp.next = None
cur.next = tmp
cur = tmp
return head
# 顺序打印单链表结点的数据
def PrintList(head):
cur = head.next
while cur != None:
print(cur.data, '', end='')
cur = cur.next
# 找出链表倒数第k个结点
def FindLastK(head, k):
if head == None or head.next == None:
return head
slow = LNode()
fast = LNode()
slow = head.next
fast = head.next
# (1)让fast指针比slow指针先前移k步
i = 0
while i < k and fast != None:
fast = fast.next # 前移k步
i += 1
# 如果链表的长度比k的值小,则返回None
if i < k:
return None
# (2)快慢指针同时往前移动。循环直到fast==None时,slow指针所指的位置即所找位置
while fast != None:
slow = slow.next
fast = fast.next
return slow
复杂度分析
- 时间复杂度为 O ( n ) O(n) O(n),只对链表进行一次遍历。
- 空间复杂度为 O ( 1 ) O(1) O(1),只需常量个指针变量来保存结点的地址信息。
主函数
if __name__ == "__main__":
head = ConstructList() # 链表头指针
result = None
print("链表:", end='')
PrintList(head)
result = FindLastK(head, 3)
if result != None:
print("\n链表倒数第3个元素为:", result.data)
参考文献
[1] 何海涛. 剑指Offer:名企面试官精讲典型编程题(第2版). 北京: 电子工业出版社,2017
[2] 张波,楚秦. Python程序员面试算法宝典. 北京:机械工业出版社,2018