Josephus问题

Josephus问题


/**
 * Josephus问题。 N个人编号从1到N,从1号开始传递土豆。
 * 经过m次传递后,清除当前拿着土豆的人, 由后面的人继续
 * 传递m次,最后一个人为胜利者。
 */
public class SanDian6 {

  public static void main(String[] args) throws Exception {
    int n = 100; // 人数   
    int m = 5; // 传递次数
    long start = System.currentTimeMillis();
    getJphus(n, m);
    long end = System.currentTimeMillis();
    System.out.println(start + "-" + end + " = " + (end -start));
    /**
     * n = 1000; end - start = 1468804564005-1468804564035 = 30;
     * n = 1,0000;          = 1468804632861-1468804633193 = 332;
     * n = 10,0000;         = 1468804697639-1468804698848 = 1209;
     * n = 100,0000;       = 1468804795804-1468804806223 = 10419;
     * n = 1000,0000;     = 1468804924934-1468805035858 = 110924;
     */
  }

  /**
   * @param n 人数
   * @param m 传递次数
   * @throws Exception 
   */
  private static void getJphus(int n, int m) throws Exception {
    if(n == 0) throw new Exception("人数不能为空");
    if(m < 0)  throw new Exception("传递次数不能为负");

    Node node = getNode(n);
    //System.out.println(node);

    int loop = 0; // 循环次数
    Node mark = node;
    Node markPre = null;

    while(n != 1){
      if(m == loop){
        System.out.println("删除数字:" + mark.val);
        // 当删除头结点时
        if(markPre == null){
          node = node.next;
          mark = node;
        }
        // 删除尾节点
        else if(mark.next == null){
          markPre.next = null;
          mark = node;
        }
        // 删除中间
        else{
          markPre.next = mark.next;
          mark = mark.next;
        }
        n--;
        loop = 0;
        continue;
      }

      if(mark.next != null){
        markPre = mark;
        mark = mark.next;
      }else{
        markPre = mark.next;
        mark = node;
      }
      loop++;
    }
    System.out.println(node);
  }

  /**
   * create linkedNode of size is n.
   * value is 1. 2. 3 ..... n
   */
  private static Node getNode(int n) {
    Node head = null;
    Node mark = null;

    for (int i = 1; i <= n; i++) {
      Node temp = new Node(i, null);
      if (i == 1) {
        head = temp;
        mark = temp;
      } 
      mark.next = temp;
      mark = mark.next;

      // 形成环形链表
      /*if(i == n)
        mark.next = head;*/
    }
    return head;
  }



}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值