PHP算法學習(8) 環形鏈表 解決約瑟夫問題

2019年2月25日17:29:17php

Josephus有過的故事:39 個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓。因而決定了自殺方式,41我的排成一個圓圈,由第1我的開始報數,每報數到第3人該人就必須自殺。而後下一個從新報數,直到全部人都自殺身亡爲止。然而Josephus 和他的朋友並不想聽從,Josephus要他的朋友先僞裝聽從,他將朋友與本身安排在第16個與第31個位置,因而逃過了這場死亡遊戲。

this

抽象出的問題是 N我的圍成一圈,從第S我的開始報數,報到C的人出圈,從出去的人的下一位,繼續從下一任開始從新報數,報到m的人出圈;如此往復,直到全部人出圈。spa

final class Kid {

    public $no;
    public $next = null;

    public function __construct($no) {
        $this->no = $no;
    }

}
<?php

/*
 * 環形鏈表 解決約瑟夫問題
 */

final class CircularLinkedList {

    public function addKid($n = 0, &$head = null) {
        for ($i = 0; $i < $n; $i++) {
            $Kid = new Kid($i + 1);
            if ($i == 0) { //第一個小孩的狀況
                $head = $Kid; //對象賦值,是引用賦值
                $head->next = $Kid; //本身指向本身
                $current = $head; //對象賦值,是引用賦值
            } else {
                $current->next = $Kid;
                $Kid->next = $head;
//                //繼續指向下一個
                $current = $current->next;
            }
        }
    }

    /*
     * $start 從幾開始
     * $count 數到幾就出圈
     */

    public function play(Kid $head, $start, $count) {
        $current = $head;
        //移動指針從$start 移動到
        while (1) {
            if ($current->no == $start) {
                break;
            }
            $current = $current->next;
        }
//        p($current);
//        pp($this->countKids($current));
//        $all = $this->countKids($current);

        while ($current->next != $current->next->next) {
            //少移動一位,方便一處節點
            for ($i = 1; $i < $count; $i++) {
                $current = $current->next;
            }
            //去除節點
//            p($current);
            p('出去的小孩是  --' . $current->next->no);
            $current->next = $current->next->next;
//            p($current);
            //移動指針,移到刪除節點的下一位就是從新數數的那個節點
            $current = $current->next;
        }
        p($current->no);
    }

    public function countKids(Kid $head) {
        $current = $head;
        $count = 1;
        while ($head->no != $current->next->no) {
            $count++;
            $current = $current->next;
        }

        return $count;
    }

}

調用指針

$CircularLinkedList = new CircularLinkedList();
$CircularLinkedList->addKid(10, $head);
$CircularLinkedList->play($head, 3, 2);

結果code

出去的小孩是  --5
出去的小孩是  --8
出去的小孩是  --1
出去的小孩是  --4
出去的小孩是  --9
出去的小孩是  --3
出去的小孩是  --10
出去的小孩是  --7
出去的小孩是  --2
6
相關文章
相關標籤/搜索