逢三退一(双向回环链表算法)

 方法一

  1. /* 用常规方法实现(双向回环链表算法)
  2.  * 
  3.  * 逢三退一:一个头和尾相连的圆形数字队列,从第一个开始数,数到三,
  4.  * 就把三的那个去掉,然后接着数,如此循环,逢三退一。
  5.  * 直到最后一个为止,求最后一个是数字队列中的第几个?
  6.  */
  7. public class Cout3Quit
  8. {
  9.     public static void main(String[] args)
  10.     {
  11.         boolean[] arr = new boolean[500]; // 创建一个布尔型数组
  12.         int contNum = 0// 数数,计算数了多少个,数到3就退1个
  13.         int index = 0// 第几个位置,数到的位置
  14.         int arrlength = arr.length; // 数字队列还有多少个
  15.         for (int i = 0; i < arr.length; i++)
  16.         {
  17.             arr[i] = true// 把数组的值得全部置为true
  18.         }
  19.         while (arrlength > 1// 留下最后一个
  20.         {
  21.             if (arr[index] == true)
  22.             {
  23.                 contNum++; // 从0开始数
  24.                 if (contNum == 2// 从0开始的,数到2就是第三个数字了
  25.                 {
  26.                     arr[index] = false// 数到第三个数,把它的值变为false
  27.                     arrlength--; // 数组长度减去1
  28.                     contNum = 0// 重新数数
  29.                 }
  30.             }
  31.             index++; // 每判断一个,加1
  32.             if (index == arr.length) // 判断是否到了最后的数字,到了,重新从0开始
  33.             {
  34.                 index = 0;
  35.             }
  36.         }
  37.         // 打印数组中有true值的那个下标值,即最后那个是第几个
  38.         for (int j = 0; j < arr.length; j++)
  39.         {
  40.             if (arr[j] == true)
  41.             {
  42.                 System.out.println(j);
  43.             }
  44.         }
  45.     }
  46. }

方法二

  1. /*
  2.  * 用面向对象方法实现(双向回环链表算法)
  3.  *  
  4.  * 逢三退一:一个头和尾相连的圆形数字队列,从第一个开始数,数到三,
  5.  * 就把三的那个去掉,然后接着数,如此循环,逢三退一。
  6.  * 直到最后一个为止,求最后一个是数字队列中的第几个?
  7.  */
  8. public class Count3Quit2
  9. {
  10.     public static void main(String[] args)
  11.     {
  12.         KidCircle kc = new KidCircle(500);
  13.         int num = 0;
  14.         Kid k = kc.first;   //从第一个开始数数
  15.         while (kc.count > 1)
  16.         {
  17.             num++;   //数数
  18.             if (num == 2)  // 从0开始的,数到2就是第三个数字了
  19.             {
  20.                 kc.delete(k);  //删除当前的k
  21.                 num = 0;       //重新数数
  22.             }
  23.             k = k.right;  //k右孩子赋给k
  24.         }
  25.         System.out.println(kc.first.id); // 打印最后的一个孩子的id
  26.     }
  27. }
  28. class Kid
  29. {
  30.     int id = 0// 孩子号码
  31.     Kid left; // 左边的孩子
  32.     Kid right; // 右边的孩子
  33. }
  34. class KidCircle
  35. {
  36.     int count = 0;
  37.     Kid first;
  38.     Kid last;
  39.     // 构造函数,构造n个孩子围成的圈
  40.     public KidCircle(int n)
  41.     {
  42.         for (int i = 0; i < n; i++)
  43.         {
  44.             add(); // 调用add方法,循环一次增加一个孩子
  45.         }
  46.     }
  47.     // 添加孩子
  48.     public void add()
  49.     {
  50.         Kid k = new Kid();
  51.         k.id = count;
  52.         if (count <= 0)
  53.         {
  54.             first = k; // 只有一个孩子
  55.             last = k;
  56.             k.left = k;
  57.             k.right = k;
  58.         }
  59.         else
  60.         {
  61.             last.right = k; // 从最后的节点开始,k成为last的右边孩子
  62.             k.left = last; // last成为k的左边孩子
  63.             k.right = first; // k成为first的右边孩子
  64.             first.left = k; // k成为first的左边孩子
  65.             last = k; // 这时候k变成了最后一个
  66.         }
  67.         count++;
  68.     }
  69.     // 删除孩子
  70.     public void delete(Kid k)
  71.     {
  72.         if (count <= 0// 没有孩子
  73.         {
  74.             return;
  75.         }
  76.         else if (count == 1// 只剩一个孩子
  77.         {
  78.             first = last = null;
  79.         }
  80.         else
  81.         {
  82.             k.left.right = k.right; // k的右孩子成为 k的左孩子 的右边孩子
  83.             k.right.left = k.left; // k的左孩子成为 k的右孩子 的左边孩子
  84.             if (k == first) // 如果k是第一个孩子first
  85.             {
  86.                 first = k.right;
  87.             }
  88.             else if (k == last) // 如果k是第一个孩子last
  89.             {
  90.                 last = k.left;
  91.             }
  92.         }
  93.         count--;
  94.     }
  95. }

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值