用不同数据结构实现约瑟夫环问题的效率对比

约瑟夫环问题是一个很经典算法。

问题描述:N个人围成一圈,从第一个人开始报数,报到m的人出圈,剩下的人继续从1开始报数,报到m的人出圈;如此往复,直到所有人出圈。(模拟此过程,输出出圈的人的序号)

解决思路:

1、创建一个有N个人的环(可以是数组或链表)

2、从第一个人开始报数,当所报数字等于m时几下这个人的位置(pos = (m-1)%N)

3、删除环中该位置的数据

4、重复1、2、3步骤,直到环中只有一个数据

下面分别用三种不同的数据结构来处理该问题:

1、用数组解决约瑟夫环问题

 /**
     * 用数组解决约瑟夫环问题
     * @param people
     * @param num
     */
    static void josephusArray(String[] people,int num){

        int len = people.length;

        while (len>1){
          int pos = (num-1)%len;
          System.out.println("出圈:"+people[pos]);
          //重新生成数组
          String[] newpeople = new String[len-1];
          int m=0;
          //数组拷贝
          for(int i=0;i<len;i++){
              if(i!=pos){
                  newpeople[m]=people[i];
                  m++;
              }
          }
          len--;
        }
        System.out.println("出圈:"+people[0]);

    }

2、用ArrayList解决问题

    /**
     * 用 ArrayList
     * @param people
     * @param num
     */
    static void josephusArrayList(ArrayList<String> people,int num){

        int len = people.size();
        while(len>1){
            int pos = (num-1)%len;
            System.out.println("出圈:"+people.get(pos));
            people.remove(pos);
            len--;
        }

        System.out.println("出圈:"+people.get(0));

    }

3、用LinkedList解决问题

/**
     * 用 LinkedList
     * @param people
     * @param num
     */
    static void josephusLinkedList(LinkedList<String> people,int num){

        int len = people.size();
        while(len>1){
            int pos = (num-1)%len;
            System.out.println("出圈:"+people.get(pos));
            people.remove(pos);
           len--;
        }
        System.out.println("出圈:"+people.get(0));

    }

最后对性能做个比较:

    public static void main(String ars[]){

        //数组
        String[] s=new String[100000];

        for(int l=0;l<100000;l++){
            s[l]=(((char)(Math.random()*26+'A')+""));
        }

        long begin = System.currentTimeMillis();
        josephusArray(s,6);
        System.out.println("数组用时: "+(System.currentTimeMillis()-begin));
        
        //ArrayList
        ArrayList<String> s2= new ArrayList();
        for(int l=0;l<100000;l++){
           s2.add(((char)(Math.random()*26+'A')+""));
        }

        begin = System.currentTimeMillis();
        josephusArrayList(s2,6);
        System.out.println("ArrayList用时:"+(System.currentTimeMillis()-begin));

        //LinkedList
        LinkedList<String> s3= new LinkedList();
        for(int l=0;l<100000;l++){
            s3.add(((char)(Math.random()*26+'A')+""));
        }
        begin = System.currentTimeMillis();
        josephusLinkedList(s3,6);
        System.out.println("LinkedList用时:"+(System.currentTimeMillis()-begin));
    }

结果如下:

数组用时: 8938
ArrayList用时:462
LinkedList用时:5

结果分析:

解决约瑟夫环问题时涉及到环中数据的删除操作,数组在内存中占用一组连续的空间,删除某个元素其他元素都要向前移动,除非删除的是最后一个元素,所以用数组解决约瑟夫环问题比较消耗资源;

ArrayList是java在数组的基础上实现的动态数组,对很多细节进行了封装,但本质还是数组;

LinkedList是用链表数据结构实现的,插入和删除数据的时间复杂度都是O(1),因此在解决约瑟夫环问题上有很大优势。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野老杂谈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值