环形单链表的约瑟夫问题
环形单链表的约瑟夫问题
题目:环形单链表的约瑟夫问题
《程序员代码面试指南》第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,纯数学问题,略复杂且不好描述。

浙公网安备 33010602011771号