找出单链表中的倒数第k个元素,例如给定单链表:1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7,则单链表的倒数第3个元素为5.
方法一:顺序遍历法
这种方法需要对单链表进行两次遍历,第一次遍历得到单链表的长度,这样我们在第二次遍历过程中就知道了什么时候找到了我们需要的那个元素了。
方法二:快慢指针法
由于单链表只能从头到尾巴依次访问链表的各个结点,因此如果我们要找链表的倒数第k个元素,也只能从头到尾巴遍历查找,设置两个指针,让其中一个指针比令一个指针先走k步(如果第k个元素存在的话),然后两个指针同时向后走,直到快指针走到最后一个元素,这时候慢指针所指向的位置就是要找的元素了。
两个方法的代码如下:
class Node: # 结点类
def __init__(self, data):
self.data = data
self.next = None
class SingleLinkList: # 单链表类
def __init__(self):
self.head = None
self.tail = None
def append(self, x): # 单链表尾部追加方法
if self.head is None:
self.head = self.tail = Node(x)
else:
self.tail.next = Node(x)
self.tail = self.tail.next
# 创建链表
test_link = SingleLinkList()
for i in range(1, 8):
test_link.append(i)
# 打印链表看一下
p = test_link.head
print("链表:", end="\t")
while p is not None:
print(p.data, end="\t")
p = p.next
print()
方法一 顺序遍历法
'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def find_it(link: SingleLinkList, k):
# 第一步获取长度
i = 0
p = link.head
while p is not None: # 循环完成后 i就是链表的长度
i += 1
p = p.next
if i < k:
return None
j = 0
p = link.head
while i - j > k: # 循环完成后 p就是倒数第三个结点
p = p.next
j += 1
return p.data
# 测试方法一
t = test_link
k = 5
print(f"倒数第{k}个元素是:", find_it(t, k), "(顺序遍历法)")
方法二 快慢指针法
def find_it(link: SingleLinkList, k):
slow = link.head # slow指向第一个元素
j = 1
p = link.head
while p is not None: # 如果链表的元素个数少于k, return None
p = p.next
j += 1
if j >= k:
break
else:
return None
fast = p # fast指向第k个元素
while fast.next is not None: # 循环结束之后fast指向最后一个元素,slow指向倒数第k个元素
slow = slow.next
fast = fast.next
return slow.data
# 测试方法二
t = test_link
k = 5
print(f"倒数第{k}个元素是:", find_it(t, k), "(快慢指针法)")
两个方法的时间复杂度都是O(n),不同在于方法一最坏可能要遍历两遍,方法二只需要遍历一遍。