• 约瑟夫环问题--javasciprt 使用数组和链表实现


    约瑟夫环问题,这是个很经典的算法题,这算法来历大家可以查百度百科就清楚。

    问题描述:N个人围成一圈,从第一个(K=1)开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,最后就剩下1

    1. 使用数组 

     1 /**
     2  * 
     3  * @param {*} n : 总数 n
     4  * @param {*} k : 起始位置,默认从第一个k=1开始,每一轮结束,下一位从1开始算起
     5  * @param {*} m :第m 个为一次结束
     6  * 
     7  */
     8 function YueSeFuHuan(n=39,k=1,m=3){
     9    let arr = [];
    10    for(let i =1;i<=n;i++){
    11        arr.push(i)
    12    }
    13    let index = k-1;//k默认为1,即从第一个人开始,索引为从0开始,所以要减一
    14    let size = n;
    15    while(size>1){
    16     index = (index + m - 1) % size;//关键是这个取模,解决如何找到要删除的那个值的索引
    17     let delRes = arr.splice(index,1)
    18     // console.log("index",index)
    19     console.log( '=>'+delRes)
    20     size--
    21    }
    22    console.log("index",index)
    23    console.log("last:"+arr[0])
    24 }
    25 //1234 =>3  124=>2  14=>4 1=>1
    26 console.time("YueSeFuHuan")
    27 YueSeFuHuan(4,1,3)
    28 console.timeEnd('YueSeFuHuan')
    29 console.log("-------------")

    2. 使用链表,单向环形链表

    (1). 特点: 每一个节点的结构,有属于自己数据的属性,还有一个指向下一个节点的指针标志,这是单向链表,最后一个节点的下一个节点指向第一个节点(头节点),我们称这是一个环形链表,链表的查询性能非常低,但是插入数据和修改数据很快

    (2). 约瑟夫环问题 的正符合我们这环形链表的数据结构

     定义一个节点类

    class TNode{
        constructor(data){
            this.data = data;//节点的数据
            this.next = null// 指向下一个节点,默认null
        }
    }

    构建链表

    class LoopOneWayList{
        constructor(n=39,k=1,m=3){
            this.n = n;
            this.k = k;
            this.m = m;
            this.init();
        }
        init(){
            let headNode = new TNode(1);//初始首节点
            let currentNode = headNode;
            let p = headNode;//默认开始为首节点
            for(let i=2;i<=this.n;i++){
                let newNode = new TNode(i);
                currentNode.next = newNode;//把当前的节点的下一节点指向新增的节点
                currentNode = newNode;// 把新增的节点重新指向当前节点,依次循环添加节点
                if(i===this.k){//这里是计算出第一次从k(k=1)个开始
                    p = currentNode
                }
            }
            currentNode.next = headNode;//最后一个节点的下一个节点指向头节点(首尾相接,形成环形)
            while(p.next!=p){
                for(let i=1;i<this.m-1;i++){
                    p = p.next;
                }
                //当 指针已经移动了m次,将改节点移除,直接修改指向
                console.log("=>"+p.next.data) 
                p.next = p.next.next;
                p = p.next;
            }
            console.log(p.next==p)
            console.log("last=>:"+p.data) 
        }
    
    }
    //1234 =>4 123=>3 12=>1 2=>2
    console.time("LoopOneWayList")
    let listNode = new LoopOneWayList(41,1,3)
    console.timeEnd('LoopOneWayList')

    上面在测试的时候,用了console.time() 方法来测试,在数据量非常大的时候,使用数组的方法比链表的性能要高很多,实际应用中,使用建议使用数组方法,但是链表的这种个人觉得更容易理解,本身它就是一种数据结构和编程思想在里面

  • 相关阅读:
    Caused by: java.lang.IllegalArgumentException: Not an managed type: class XXX
    SpringBoot配置文件详细解析
    解决eclipse环境下maven项目tomcat启动,未加载到项目的问题
    CSS+元素,鼠标事件触发鼠标模形变成手状的形状
    LeetCode-Wildcard Matching
    LeetCode-NQueensII
    LeetCode-Climbing Stairs
    LeetCode-Word Search
    LeetCode-Minimum Window Substring
    LeetCode-Largest Rectangle in Histogram
  • 原文地址:https://www.cnblogs.com/beyonds/p/13691641.html
Copyright © 2020-2023  润新知