zoukankan      html  css  js  c++  java
  • 使用环形链表解决约瑟夫(丢手帕)问题

    约瑟夫问题:

      设编号为1,2,3...n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依此类推,直到所有人出列为止,由此产生一个出队编号的序列,并求出最后出列的人是哪个?

    1.先死后活:

    将问题简化成:有4个人围坐一圈,从编号1的人开始报数,数到2的人出列,依次类推。

    2.创建节点类:

     1 /**
     2  * 节点类
     3  * @author SCOTT
     4  *
     5  */
     6 public class Child {
     7     /*编号*/
     8     int no;
     9     /*下一个节点*/
    10     Child next;
    11     
    12     public Child(int no){
    13         this.no = no;
    14     }
    15 }

    3.创建环形链表,并返回第一个节点

     1 /**
     2      * 创建一个环形链表
     3      * @param head 指定第一个节点的头指针
     4      * @param num 环形链表个数
     5      * @return 返回指定第一个节点的头指针
     6      */
     7     private static Child createCircleLink(Child head,int num){
     8         //要报障head不改变,让cur游走各个节点之间
     9         Child cur = null;
    10         for(int i=0;i<num;i++){
    11             Child child = new Child(i+1);
    12             if(i==0){
    13                 head = child;
    14                 child.next = child;
    15             }else{
    16                 cur.next = child;
    17                 child.next = head;
    18             }
    19             cur = child;
    20         }
    21         return head;
    22     }

    4.测试环形链表是否创建成功

     1 /**
     2      * 遍历环形链表节点
     3      * @param head
     4      */
     5     private static void ergodicCircleLink(Child head){
     6         if(head == null)
     7             return;
     8     
     9         Child cur = head;
    10         while(cur.next != head){
    11             System.out.println("当前节点:"+cur.hashCode()+"	下一个节点:"+cur.next.hashCode());
    12             cur = cur.next;
    13         }
    14         //当前cur指向最后一个节点
    15         System.out.println("当前节点:"+cur.hashCode()+"	下一个节点:"+cur.next.hashCode());
    16     }

    5.环形链表创建成功后,就可以玩游戏了

     1 /**
     2      * 从第一个人开始数,数2下
     3      * @param head
     4      * @param k 从k开始数
     5      * @param m 数m下
     6      * @param n 链表个数
     7      */
     8     private static void play(Child head, int k, int m, int n){
     9         if(head == null)
    10             return;
    11         
    12         if(!(k>=1 && k<= n)){
    13             System.out.println("指定人数不在范围内,"+k+">"+n);
    14             return;
    15         }
    16         
    17         //指向当前节点
    18         Child cur = head;
    19         //需要一个与cur相邻的并位于cur后一位的指针,初始位置让他指向最后一个节点,便于删除节点
    20         Child tail = null;
    21         while(cur.next != head){
    22             cur = cur.next;
    23         }
    24         tail = cur;
    25         cur = head;
    26         
    27         //找到第k个位置
    28         for(int i=0;i<k-1;i++){
    29             cur = cur.next;
    30             tail = tail.next;
    31         }
    32         
    33         while(cur != tail){
    34             //开始数数:移动一次,代表数了2下
    35             for(int i=0;i<m-1;i++){
    36                 cur = cur.next;
    37                 tail = tail.next;
    38             }
    39             System.out.println("第"+cur.no+"号小朋友出列!");
    40             //删除cur指向的节点
    41             //让cur再往下移一个节点
    42             cur = cur.next;
    43             tail.next = cur;
    44         }
    45         System.out.println("获胜的小朋友:"+tail.no);
    46     }

    6.测试:

     1 public static void main(String[] args) {
     2         int n = 4;
     3         int m = 2;
     4         int k = 1;
     5         //指向环形链表的第一个节点,便于链表的操作
     6         Child head = null;
     7         head = createCircleLink(head, n);
     8         //ergodicCircleLink(head);
     9         play(head, k, m, n);
    10 }

  • 相关阅读:
    wget/curl查看请求响应头信息
    对软件测试的理解
    负载测试、压力测试和性能测试的区别
    经典测试面试题
    软件测试的目的和任务
    为cloudstack搭建ceph文件系统
    多网卡绑定实例
    牛客多校5 A-gpa(01分数规划)
    HDU
    2018ACM-ICPC宁夏邀请赛 A-Maximum Element In A Stack(栈内最大值)
  • 原文地址:https://www.cnblogs.com/myCodingSky/p/3803767.html
Copyright © 2011-2022 走看看