Loading

环形单链表的约瑟夫问题

环形单链表的约瑟夫问题

题目:环形单链表的约瑟夫问题

《程序员代码面试指南》第17题 P50 难度:士★☆☆☆

本题普通解法很简单,只需要不断的遍历环形单链表即可,报数为m的节点将其从链表中去除,直到剩下最后一个节点。

另外注意一下异常情况,head==null或者只有1个节点或者报数m<1则直接返回

牛客题解代码如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main{

    public static class Node {

    public int value;
    public Node next;

    public Node(int value) {
        this.value = value;
    }
}
    
    public static Node josephusKill(Node head, int m) {
        if (head == null || head.next == head || m < 1) {
            return head;
        }
        Node last = head;
        while (last.next != head) {
            last = last.next;
        }
        int count = 0;
        while (head != last) {
            count++;
            if (count == m) {
                last.next = head.next;
                count = 0;
            } else {
                last = last.next;
            }
            head = last.next;
        }
        return head;
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String[] parameters = bufferedReader.readLine().split(" ");
        int l = Integer.parseInt(parameters[0]);
        int m = Integer.parseInt(parameters[1]);
        Node head = new Node(1);
        Node cur = head;
        for (int i = 2; i <= l; i++) {
            cur.next = new Node(i);
            cur = cur.next;
        }
        cur.next = head;
        head = josephusKill(head, m);
        System.out.println(head.value);
    }
}

进阶问题

题目:环形单链表的约瑟夫问题(进阶)

《程序员代码面试指南》第17题 P51 难度:校★★★☆

普通解法的时间复杂度为O(n×m),进阶问题要求时间复杂度达到O(n)

看了书上的思路,大致概括一下:

首先遍历环形单链表,第一个报数m的节点将其去除,剩下的节点重新编号。此时新老编号存在一定的对应关系

然后再对剩下的节点再执行以上操作,直到只剩最后一个节点。

代码实现是使用递归,如下:

public int getLive(int i, int m) {
  if(i == 1) {
    return 1;
  }
  return (getLive(i-1, m) + m-1) % i + 1;

详细原理参照书P51-55,纯数学问题,略复杂且不好描述。

posted @ 2021-11-12 14:36  幻梦翱翔  阅读(38)  评论(0)    收藏  举报