猴子选大王
题目描述:
N个猴子围成一个圈
1、从第一只猴子开始报数,第一只猴子报1
2、每个报2的猴子退出,然后从下一只猴子重新开始报数,
3、要求输出退出的顺序和最后剩下的人
解题思路:
解法一:用数组解决,用数组存放1,2,3…N来表示N个猴子,然后不停的遍历数组,对于被选中的编号,我们可以将其标记为0,来表示该猴子已出局,然后按这种方法一直遍历数组,直到数组只有一个非0元素时,就表示已经找出最后一个猴子。
解法二:利用环形链表解决,这也是大多数人看到这个题第一个想出的方法,毕竟操作简单,易实现。它的具体思路就是用一个环形链表存放1,2,3…N来表示N个猴子。在利用一个count字段,初始值为1,统计count次数,当count = 2 时,就删除该节点(链表的删除结点在此不在展开),在使count置1, 循环的结束条件就是head.next = head即剩的最后一个元素。
public class ChooseKing {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入猴子数: ");
int m = sc.nextInt();
System.out.println("请输入出去间隔");
int n = sc.nextInt();
int count = 1;
ListNode head = createListNode(m);
ListNode pre = null;
while(head.next != head){
pre = head;
head = head.next;
count++;
if(count == n){
System.out.println("出局者是第" + head.val);
pre.next = head.next;
head = pre.next;
count = 1;
}
}
System.out.println("最后出局者是第" + head.val);
}
public static ListNode createListNode(int m){
ListNode head = new ListNode(1);
if(m == 1) return head;
ListNode cur = head;
for(int i = 2;i <= m;i++){
ListNode tmp = new ListNode(i);
cur.next = tmp;
cur = tmp;
}
cur.next = head;
return head;
}
}
class ListNode{
public int val;
public ListNode next;
public ListNode(int val){
this.val = val;
}
}
解法三:是用递归来解决的,此方法只能输出最后出局的猴子编号,所以下面会直接附上代码。
/**
*
* @param n 猴子个数
* @param m 第m个猴子出去
* @return
*/
public static int chooseKing(int n,int m){
return n == 1? n:(chooseKing(n-1,m) + m -1) % n + 1;
}