python经典算法面试题1.5:如何找出单链表中的倒数第K个元素

本题目摘自《Python程序员面试算法宝典》,我会每天做一道这本书上的题目,并分享出来,统一放在我博客内,收集在一个分类中。

【微软笔试题】

难度系数:⭐⭐⭐
考察频率:⭐⭐⭐⭐⭐

题目描述:

找出单链表中的倒数第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()

# 方法一 顺序遍历法
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),不同在于方法一最坏可能要遍历两遍,方法二只需要遍历一遍。

posted @ 2019-10-29 09:28  段明  阅读(956)  评论(0编辑  收藏  举报