📜  门| GATE-CS-2006 |第 70 题(1)

📅  最后修改于: 2023-12-03 15:28:42.805000             🧑  作者: Mango

门| GATE-CS-2006 |第 70 题

该问题是计算机科学中的一个经典问题,考察了程序员的逻辑思维和算法实现能力。

题目描述

n 个人,编号为 1n。这 n 个人排成了一个圆,每个人都有一个指向下一个人的箭头。

现在,从第一个人开始,从 1 开始计数,每 m 个人就将当前指向的人删除,然后再从下一个人开始重新计数,直到删除了所有人为止。

给定 nm,问最后一个被删除的人的编号是多少?

解题思路

我们可以用链表实现,每个结点代表一个人。我们首先从头结点开始,每计数到第 m 个结点,就将其删除。

这个计数的操作可以通过模拟链表中每个结点的下一个结点,来实现循环。当到达尾结点时,我们继续计数到头结点。

具体来说,我们可以每删除一个结点就让当前指针指向下一个结点的下一个结点,实现「跳过」当前结点。

当只剩下一个结点时,它便是最后一个被删除的人。

代码实现

下面是一个用 Python 实现的示例代码:

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    def lastRemaining(self, n: int, m: int) -> int:
        # 构造环形链表
        head = ListNode(0)
        p = head
        for i in range(1, n):
            p.next = ListNode(i)
            p = p.next
        p.next = head

        # 循环计数并删除结点,直到只剩下一个结点
        q = head
        while q.next != q:
            for i in range(m - 1):
                p = q
                q = q.next
            p.next = q.next
            q = p.next

        return q.val
总结

本题考察了链表、循环计数等基本数据结构和算法,需要熟练掌握链表相关操作。通过模拟链表的循环特性,可以方便地解决问题。同时,如何判断边界情况和特殊情况也是需要考虑的。