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

<script type="text/javascript"> </script> <script type="text/javascript"> </script>

 方法一

  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. }

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值