漢諾塔遞歸算法

起源:

  漢諾塔(又稱河內塔)問題是源于印度一個古老傳說的益智玩具。大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。并且規定,在小圓盤上不能放大圓盤,在三根柱子之間一次只能移動一個圓盤。

抽象為數學問題:

  如下圖所示,從左到右有A、B、C三根柱子,其中A柱子上面有從小疊到大的n個圓盤,現要求將A柱子上的圓盤移到C柱子上去,期間只有一個原則:一次只能移到一個盤子且大盤子不能在小盤子上面,求移動的步驟和移動的次數

hanoi.jpeg

?

解:(1)n == 1

??????       第1次? 1號盤? A---->C?????? sum = 1 次

?????? (2)? n == 2

??????       第1次? 1號盤? A---->B

??????      ?第2次? 2號盤? A---->C

??????       第3次? 1號盤? B---->C??????? sum = 3 次

  (3)n == 3

        第1次? 1號盤? A---->C

        第2次? 2號盤? A---->B

        第3次? 1號盤? C---->B

        第4次? 3號盤? A---->C

        第5次? 1號盤? B---->A

        第6次? 2號盤? B---->C

        第7次? 1號盤? A---->C??????? sum = 7 次

不難發現規律:1個圓盤的次數 2的1次方減1

       2個圓盤的次數 2的2次方減1

? ? ? ? ? ? ? ? ? ? ? ? ?3個圓盤的次數 2的3次方減1

? ? ? ? ? ? ? ? ? ? ? ? ?。? 。?? 。??? 。?? 。?

? ? ? ? ? ? ? ? ? ? ? ? ?n個圓盤的次數 2的n次方減1

?故:移動次數為:2^n - 1

有兩種解法,一種是遞歸,一種是棧。先來看遞歸的實現

  • 將 n - 1 個圓盤從 A 移動到 C(借助 B)
  • 將第 n 個圓盤從 A 移動到 B
  • 將 n - 1 個圓盤從 C 移動到 B(借助 A)

移動次數為 2 的 n 次方 - 1

let count = 0
function move(number, from, to, depend) {console.log(`將第 ${number} 號圓盤從 ${from} 移動到 ${to}`)count++
}
// 將 n 個圓盤從 a 移動到 b 借助 c
function hanoi(n, a, b, c) {if (n === 0) {return}hanoi(n - 1, a, c, b) // 將 n -1 個圓盤從 a 移動到 c,借助 bmove(n, a, b) // 將第 n 個圓盤從 a 移動到 bhanoi(n - 1, c, b, a) // 將 n -1 個圓盤從 c 移動到 b,借助 a
}
hanoi(3, 'A', 'B', 'C')
console.log('移動次數', count)
// 將第 1 號圓盤從 A 移動到 B
// 將第 2 號圓盤從 A 移動到 C
// 將第 1 號圓盤從 B 移動到 C
// 將第 3 號圓盤從 A 移動到 B
// 將第 1 號圓盤從 C 移動到 A
// 將第 2 號圓盤從 C 移動到 B
// 將第 1 號圓盤從 A 移動到 B
// 移動次數 7

重構上面,使用一個函數

function hanoiRecursion(n, a, b, c, moves = []) {if (n === 0) {return moves}hanoiRecursion(n - 1, a, c, b, moves) // 將 n -1 個圓盤從 a 移動到 c,借助 bmoves.push([a, b]) // move(n, a, b) // 將第 n 個圓盤從 a 移動到 bhanoiRecursion(n - 1, c, b, a, moves) // 將 n -1 個圓盤從 c 移動到 b,借助 areturn moves
}
let moves = hanoiRecursion(3, 'A', 'B', 'C')
console.log('移動路徑', moves)
console.log('移動次數', moves.length)
// // 移動路徑
// // [
// //  ["A", "B"], ["A", "C"], ["B", "C"], ["A", "B"],
// //  ["C", "A"], ["C", "B"], ["A", "B"]
// // ]
// // 移動次數 7

使用棧其實也需要使用遞歸,只是我們通過 3 個棧,表示三個圓柱,可以實時看對應的效果

// 棧類
class Stack {constructor() {this.count = 0;this.items = {};}// 向棧中插入元素push(element) {this.items[this.count] = element;this.count++;}isEmpty() {return this.count === 0;}size() {return this.count;}get length() {return this.count;}// 從棧中彈出元素pop() {if (this.isEmpty()) {return undefined;}this.count--;const result = this.items[this.count];delete this.items[this.count];return result;}peek() {if (this.isEmpty()) {return undefined;}return this.items[this.count - 1];}clear() {this.items = {};this.count = 0;// 或者// while(!this.isEmpty()) {//   this.pop()// }}toString() {if (this.isEmpty()) {return "";} else {let i = 0,len = this.count,result = "";while (i < len) {result += this.items[i];if (i !== len - 1) {result += ",";}i++;}return result;}}
}function hanoi(n, source, dest, depend, a, b, c, moves = []) {if (n === 0) {return}// 將 n - 1 個圓盤從 source 移動到 dependhanoi(n - 1, source, depend, dest, a, c, b, moves) moves.push([a, b])// 將第 n 個圓盤從 source 移動到 destdest.push(source.pop()) // 將 n - 1 個圓盤從 depend 移動到 desthanoi(n - 1, depend, dest, source, c, b, a, moves) 
}
function hanoiStack(n) {let source = new Stack()let dest = new Stack()let depend = new Stack()let count = nwhile (count) {source.push(count--)}let moves = []console.log('source: ', source)hanoi(n, source, dest, depend, 'A', 'B', 'C', moves)console.log('source: ', source)console.log('dest: ', dest)console.log('depend: ', depend)return moves
}
console.log(hanoiStack(3))
// source:  Stack { count: 3, items: { '0': 3, '1': 2, '2': 1 } }
// source:  Stack { count: 0, items: {} }
// dest:  Stack { count: 3, items: { '0': 3, '1': 2, '2': 1 } }
// depend:  Stack { count: 0, items: {} }
// [
//   [ 'A', 'B' ],
//   [ 'A', 'C' ],
//   [ 'B', 'C' ],
//   [ 'A', 'B' ],
//   [ 'C', 'A' ],
//   [ 'C', 'B' ],
//   [ 'A', 'B' ]
// ]

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247257.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247257.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247257.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java編程基礎階段筆記 day 07 面向對象編程(上)

? 面向對象編程 筆記Notes 面向對象三條學習主線 面向過程 VS 面向對象 類和對象 創建對象例子 面向對象的內存分析 類的屬性&#xff1a;成員變量 成員變量 VS 局部變量 類的方法 方法的重載 可變個數形參 面向對象&#xff1a;封裝性 訪問權限修飾符 構造方法&…

談“發表(撰寫)學術論文的注意事項”

題記&#xff1a;做兩個核心學術期刊的“數字圖像處理”類審稿專家有一段時間了&#xff0c;在審稿過程中發現存在很多問題&#xff0c;所以在此就撰寫學術論文過程中的一些注意事項&#xff0c;跟大家交流一下&#xff08;當然&#xff0c;文中的很多觀點也是一些資深主編的看…

Vue/Angular中父窗口新開的子窗口關閉的時候刷新父窗口

最近遇到一個項目需求&#xff1a;Angular中父窗口新開的子窗口提交完信息關閉的時候刷新父窗口。 知識點&#xff1a; window.opener 概述 返回打開當前窗口的那個窗口的引用&#xff0c;例如&#xff1a;在window A中打開了window B&#xff0c;B.opener 返回 A. 語法 …

圖像邊緣特征

圖像邊緣是圖像的重要特征&#xff0c;是圖像中特性&#xff08;如像素灰度、紋理等&#xff09;分布的不連續處&#xff0c;圖像周圍特性有階躍變化或屋脊狀變化的那些像素集合。圖像的邊緣部分集中了圖像的大部分信息&#xff0c;一幅圖像的邊緣結構與特點往往是決定圖像特質…

HDU 6631 line symmetric(枚舉)

首先能想到的是至少有一對相鄰點或者中間間隔一個點的點對滿足軸對稱&#xff0c;那么接下來只需要枚舉剩下的點對是否滿足至多移動一個點可以滿足要求。 第一種情況&#xff0c;對于所有點對都滿足要求&#xff0c;那么Yes。 第二種情況&#xff0c;有一個點不滿足要求&#x…

學習數字圖像處理經驗談

一、面向應用&#xff1a;層層分解、抓住要點 我們學習數字圖像處理的最終目的還是應用&#xff0c;不管是用它來研制產品還是研發項目抑或是研究課題&#xff0c;都要用數字圖像處理的理論、方法和技術來解決實際問題。在此過程中&#xff0c;提高效率是非常重要的&#xff0c…

讀javascript百煉成仙笑死筆記一

“自然是這樣的&#xff0c;但是我現在這樣改一下&#xff0c;你說結果是多少呢&#xff1f;”葉小凡詭異地笑了笑&#xff0c;然后打出一段比較奇特的代碼。 var a 1; var b; var sum (b a --a) a-- b; “噗&#xff01;”看到這段代碼&#xff0c;對面弟子差點一口老血…

C#調用存儲過程的通用類

usingSystem;usingSystem.Collections.Generic;usingSystem.Text;usingSystem.Data.SqlClient;usingSystem.Collections;usingSystem.Data;//摘要&#xff1a;數據訪問助手。//作者&#xff1a;ZhiQiao//日期&#xff1a;2008/07/02namespaceZhiQiao.DataAccessHelper{ //存…

圖靈獎得主(一)

本文轉自&#xff1a;http://bbs.gxnu.edu.cn/bbsanc.php?path%2Fgroups%2FGROUP_5%2FProgramming%2Fother%2FM.1029997222.A A.M. Turing Award ACMs most prestigious technical award is accompanied by a prize of $25,000. It is given to an individual selected fo…

react-router-dom@6獲取路由傳參

目錄 參數獲取 1、子路由形式攜帶 2、問號(?)形式參數 3、事件跳轉傳參 router/index.tsx import App from "App"; import Home from "pages/Home"; import List from "pages/List"; import Detail from "pages/Detail"; import…

圖靈獎得主(二)

本文轉自&#xff1a;http://bbs.gxnu.edu.cn/bbsanc.php?path%2Fgroups%2FGROUP_5%2FProgramming%2Fother%2FM.1029997222.A 1987年度的圖靈獎授予了IBM沃特森研究中心老資格的研究員 約翰科克(Johncocke)。 科克是從機械到數學、又從數學轉到 計算機方向上來的學者。…

jQuery效果之滑動

jQuery 滑動方法有三種&#xff1a;slideDown()、slideUp()、slideToggle()。 jQuery slideDown() 方法用于向下滑動元素&#xff0c; 語法&#xff1a;$(selector).slideDown(speed,callback); 可選的 speed 參數規定效果的時長。它可以取以下值&#xff1a;"slow"、…

Error: This command has to be run with superuser privileges (under the root user on most systems).

意思是錯誤&#xff1a;此命令必須以超級用戶權限&#xff08;在大多數系統上以root用戶權限&#xff09;運行。所以當前的用戶是普通用戶&#xff0c;需要切換為超級用戶&#xff08;root用戶&#xff09;先輸入在命令行中輸入 su root 然后會出現Password&#xff1a;&#…

圖靈獎得主(三)

本文轉自&#xff1a;本文轉自&#xff1a;http://bbs.gxnu.edu.cn/bbsanc.php?path%2Fgroups%2FGROUP_5%2FProgramming%2Fother%2FM.1029997222.A 繼1979年度圖靈獎首次授予一位加拿大學者K.E.Iverson之后&#xff0c; 1989年度的圖靈 獎又一次授予加拿大學者威廉凱亨(Willia…

對微信公共號的理解

通過redirect_uri獲取code 通過code和appid 獲取access_token 進行鑒權 轉載于:https://www.cnblogs.com/zhouyideboke/p/11309752.html

vue3 v-model變化

概覽 就變化內容而言&#xff0c;此部分屬于高階內容&#xff1a; 非兼容&#xff1a;用于自定義組件時&#xff0c;v-model的 prop 和事件默認名稱已更改&#xff1a; prop&#xff1a;value -> modelValue&#xff1b;event&#xff1a;input -> update:modelValue&a…

圖靈獎得主(四)

本文轉自&#xff1a;本文轉自&#xff1a;本文轉自&#xff1a;http://bbs.gxnu.edu.cn/bbsanc.php?path%2Fgroups%2FGROUP_5%2FProgramming%2Fother%2FM.1029997222.A 1991年度的圖靈獎授予了愛丁堡大學計算機科學系教授羅 賓米爾納(Robin Milner)。米爾納是繼M.V.Wilkes(1…

sql 日期類型空值等于 1900-01-01

SQL server 中查詢&#xff1a;select cast( as datetime) 結果&#xff1a;1900-01-01 00:00:00.000 做為判斷條件的話&#xff0c;要注意。不能直接 轉載于:https://www.cnblogs.com/meng9527/p/11311765.html

koa洋蔥模型

Koa 和 Express 都會使用到中間件 Express的中間件是順序執行&#xff0c;從第一個中間件執行到最后一個中間件&#xff0c;發出響應如上圖 Koa是從第一個中間件開始執行&#xff0c;遇到 next 進入下一個中間件&#xff0c;一直執行到最后一個中間件&#xff0c;在逆序&#x…

圖靈獎得主(五)

[1993]斯坦恩斯--"打工"帶來的機遇 斯坦恩斯是學數學出身的。1958年他在卡爾頓學院(Carlton College)取 得數學學士學位后進入普林斯頓大學研究生院&#xff0c;用了3年時間就 取得博士學位&#xff0c;其博士論文課題是關于博奕論的。 斯坦恩斯跨進計算機科…