约瑟夫环-猴子选大王(变型题)

接着上篇猴子选大王继续展开,上篇讲的是有m个猴子,从第一个猴子开始报数,当报到n时,第n个猴子出去,从n+1猴子开始,从1继续报数。

这篇我们来说,从任意猴子k的位置开始报数,当报到n时,第n个猴子出去,从n+1猴子开始,从1继续报数

问题描述:

约瑟夫环运作如下:

         1、一群猴子围在一起坐成环状(如:N)

         2、从某个编号开始报数(如:K)

         3、数到某个数(如:M)的时候,此猴出列,下一个猴子重新报数

         4、一直循环,直到所有猴子出列,约瑟夫环结束,同时输出最后的大王。

解题思路:

我们还是用循环链表解决,这里有两种方法,一种是根据上篇讲的那样,构造循环链表,利用循环操作将头指针指向第k个结点上,后续操作和上篇一样

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入猴子数N: ");
        int n = sc.nextInt();
        System.out.println("请输入开始报数编号K: ");
        int k = sc.nextInt();
        System.out.println("请输入出列数M: ");
        int m = sc.nextInt();
        if(k > n || m > n) {
            System.out.println("编号K或者M不能大于猴子总数N");
            System.exit(0);
        }
        ListNode head = createListNode(n);
        while(k != 1){
            head = head.next;
            k--;
        }
        int count = 1;
        ListNode pre = null;
        while(head.next != head){
            pre = head;
            head = head.next;
            count++;
            if(count == m){
                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;
    }
}

 

另一种就是在构造循环链表过程中,直接将头指针定义为第k个猴子,后续操作和上篇代码一样

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入猴子数N: ");
        int n = sc.nextInt();
        System.out.println("请输入开始报数编号K: ");
        int k = sc.nextInt();
        System.out.println("请输入出列数M: ");
        int m = sc.nextInt();
        if(k > n || m > n) {
            System.out.println("编号K或者M不能大于猴子总数N");
            System.exit(0);
        }
        ListNode head = createListNode(n, k);
        int count = 1;
        ListNode pre = null;
        while(head.next != head){
            pre = head;
            head = head.next;
            count++;
            if(count == m){
                System.out.println("当前出局人是: "+ head.val);
                pre.next = head.next;
                head = pre.next;
                count = 1;
            }
        }
        System.out.println("最后的大王是: "+ head.val);
    }

    public static ListNode createListNode(int n,int k){
        ListNode head = new ListNode(k);
        ListNode cur = head;
        for(int i = k;i<n;i++){
            ListNode tmp = new ListNode(i + 1);
            cur.next = tmp;
            cur = tmp;
        }
        for(int i = 0;i<k - 1;i++){
            ListNode tmp = new ListNode(i + 1);
            cur.next = tmp;
            cur = tmp;
        }
        cur.next = head;
        return head;
    }

约瑟夫环-猴子选大王(变型题)

 

 

 

上一篇:遍历一个List有哪些不同的方式?


下一篇:objective-c GCD