程序员代码面试指南 2.6:环形链表的约瑟夫问题

解法一

1、思路

  • 遍历环形链表,删除每 m 个节点,直到链表中剩下一个元素为止;

  • 一共要删除 n - 1 个节点,每次删除要遍历 m 次,时间复杂度为 ,略高。

2、代码

#include <iostream>
#include <memory>

using namespace std;

struct ListNode                         //单链表结构体
{
    int val;
    shared_ptr<ListNode> next;
    ListNode(int _val) : val(_val), next(nullptr) {}
};

shared_ptr<ListNode> createList(int n)  //构造环形链表
{
    shared_ptr<ListNode> head = make_shared<ListNode>(0);
    auto p = head;

    for (int i = 1; i <= n; ++ i)
    {
        p = p->next = make_shared<ListNode>(i);
    }

    p->next = head->next;
    return head->next;
}

//约瑟夫环问题,每次删去环中第m个节点
shared_ptr<ListNode> josephusKill(shared_ptr<ListNode> head, int m)
{
    if (head == nullptr || head->next == head || m < 1) return head;

    auto last = head;
    while (last->next != head)  //保存最后一个节点
    {
        last = last->next;
    }

    int cnt = 0;
    while (head != last)        //当 head == last 时,链表中只剩下一个节点了
    {
        if ( ++ cnt == m)       //跳过每 m 个节点
        {
            last->next = last->next->next;
            cnt = 0;
        }
        else
        {
            last = last->next;
        }

        head = last->next;
    }

    return head;
}

int main()
{
    int n, m;
    cin >> n >> m;

    shared_ptr<ListNode> head = createList(n);

    while (head->next->val != head->val)    //循环删除,直到剩下一个节点为止
    {
        head = josephusKill(head, m);
    }

    cout << head->val << endl;

    return 0;
}

主要是为左程云的《程序员代码面试指南》这本书改写C++版的题解。

全部评论

相关推荐

11-04 19:05
已编辑
东莞城市学院 单片机
不知道怎么取名字_:你这个要实习两年?哪有这么久的,感觉就是即使你毕业了,但还按实习的话,是不是不用给你缴社保公积金啥的
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务