【Code pratice】—— 纸牌三角形
Date:2022?10?04\color{FFCC99}{Date:2022-10-04}Date:2022?10?04
Everyone\color{FFCC99}{Everyone}Everyone has\color{FFCC99}{has}has to\color{FFCC99}{to}to grow\color{FFCC99}{grow}grow up,\color{FFCC99}{up,}up, but\color{FFCC99}{but}but not\color{FFCC99}{not}not everyone\color{FFCC99}{everyone}everyone understand\color{FFCC99}{understand}understand grew\color{FFCC99}{grew}grew up!\color{FFCC99}{up!}up!
文章目錄
- 🍕1. 紙牌三角形🍕
- 🍔題目🍔
- 🍔思路🍔
- 🍔代碼🍔
- 🍔總結(jié)🍔
🍕1. 紙牌三角形🍕
🍔題目🍔
A,2,3,4,5,6,7,8,9 共9張紙牌排成一個(gè)正三角形(A按1計(jì)算)。要求每個(gè)邊的和相等。如果考慮旋轉(zhuǎn)、鏡像后相同的算同一種,一共有多少種不同的排法呢?三角形如下
A 2 34 5 6 7 8 9🍔思路🍔
本題是典型的全排列算法題目,通過對(duì)9個(gè)數(shù)字進(jìn)行全排列,就可以計(jì)算出所有的三角形種類
什么是全排列?
全排列算法是一種經(jīng)典的遞歸算法,如{1,2,3}的全排列為{1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2}, {3, 2, 1},一共6鐘排列結(jié)果。全排列就是將全部可能出現(xiàn)的排序都列出來。而每一個(gè)數(shù)字能出現(xiàn)在任一個(gè)位置,如果不固定的話,那排序起來就會(huì)十分混亂,排序結(jié)果也不好記錄,所以遞歸求解的思路是每一次全排列都固定一個(gè)元素,然后求剩下元素的全排列,直到就剩一個(gè)元素的全排列時(shí)結(jié)束本次全排列,而且每一次全排列完成后,都應(yīng)先將數(shù)字排序恢復(fù)到本次全排列開始前的狀態(tài),以保證下一次的全排列都是基于初始狀態(tài)進(jìn)行的。
舉個(gè)例子
對(duì){1, 2, 3}進(jìn)行全排列,下面按照上述全排列遞歸算法的思路實(shí)際模擬一遍
(每一次遞歸的第一步都是先判斷當(dāng)前遍歷的是不是最后一個(gè)元素,如果是則說明全排列完成一次)
- 第1次遞歸調(diào)用,從頭開始遍歷,此時(shí)選擇當(dāng)前第一個(gè)元素1為固定元素,并將固定元素1與當(dāng)前遍歷的元素1進(jìn)行換位,剩余元素為{2, 3},此時(shí)排列為{1, 2, 3};
- 第2次遞歸調(diào)用(基于第1次):從剩余元素開始遍歷,此時(shí)選擇當(dāng)前第一個(gè)元素2為固定元素,并將固定元素2與當(dāng)前遍歷的元素2進(jìn)行換位,剩余元素為{3},此時(shí)排列為{1, 2, 3};
- 第3次遞歸調(diào)用(基于第2次):從剩余元素開始遍歷,此時(shí)選擇當(dāng)前第一個(gè)元素3為固定元素,并將固定元素3與當(dāng)前遍歷的元素3進(jìn)行換位,剩余元素為空,此時(shí)排列為{1, 2, 3};
- 第4次遞歸調(diào)用(基于第3次):因?yàn)榈?次遞歸調(diào)用時(shí)已經(jīng)選擇到了最后一個(gè)元素,遍歷結(jié)束,取得第一個(gè)全排列結(jié)果{1, 2, 3},第4次遞歸結(jié)束;
- 因?yàn)榈?次遞歸調(diào)用已經(jīng)遍歷結(jié)束,將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(3 <-> 3),得到開始前的排列{1, 2, 3};
- 第5次遞歸調(diào)用(基于第2次):第2次遞歸往下遍歷,將固定元素2與遍歷元素3進(jìn)行換位,剩余元素為空,此時(shí)排列為{1, 3, 2};
- 第6次遞歸調(diào)用(基于第5次):因?yàn)榈?次遞歸調(diào)用時(shí)已經(jīng)選擇到了最后一個(gè)元素,遍歷結(jié)束,取得第二個(gè)全排列結(jié)果{1, 3, 2}, 第6次遞歸結(jié)束;
- 因?yàn)榈?次遞歸調(diào)用已經(jīng)遍歷結(jié)束,將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(3 <-> 2),得到開始前的排列{1, 2, 3};
- 因?yàn)榈?次遞歸調(diào)用已經(jīng)遍歷結(jié)束,所以將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(2 <-> 2),得到開始前的排列{1, 2, 3};
- 第7次遞歸調(diào)用(基于第1次):第1次遞歸往下遍歷,并將固定元素1與遍歷元素2進(jìn)行換位,此時(shí)排列為{2, 1, 3};
- 第8次遞歸調(diào)用(基于第7次):此時(shí)選擇剩余元素的第一個(gè)元素3為固定元素,并將固定元素3與當(dāng)前遍歷的元素3進(jìn)行換位,剩余元素為空,此時(shí)排列為{2, 1, 3};
- 第9次遞歸調(diào)用(基于第8次):因?yàn)榈?次遞歸調(diào)用時(shí)已經(jīng)選擇到了最后一個(gè)元素,遍歷結(jié)束,取得第三個(gè)全排列結(jié)果{2, 1, 3},第9次遞歸結(jié)束;
- 因?yàn)榈?次遞歸調(diào)用已經(jīng)遍歷結(jié)束,將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(3 <-> 3),得到開始前的排列{2, 1, 3};
- 第10次遞歸調(diào)用(基于第7次):第7次遞歸往下遍歷,將固定元素1與遍歷元素3進(jìn)行換位,剩余元素為空,此時(shí)排列為{2, 3, 1};
- 第11次遞歸調(diào)用(基于第10次):因?yàn)榈?1次遞歸調(diào)用時(shí)已經(jīng)選擇到了最后一個(gè)元素,遍歷結(jié)束,取得遍歷結(jié)束,取得第四個(gè)全排列結(jié)果{2, 3, 1}, 第11次遞歸結(jié)束;
- 因?yàn)榈?0次遞歸調(diào)用已經(jīng)遍歷結(jié)束,將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(1 <-> 3),得到開始前的排列{2, 1, 3};
- 因?yàn)榈?次遞歸調(diào)用已經(jīng)遍歷結(jié)束,將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(2 <-> 1),得到開始前的排列{1, 2, 3};
- 第12次遞歸調(diào)用(基于第1次):第1次遞歸往下遍歷,并將固定元素1與遍歷元素3進(jìn)行換位,剩余元素為{1},此時(shí)排列為{3, 2, 1};
- 第13次遞歸調(diào)用(基于第12次):此時(shí)選擇剩余元素第一個(gè)元素1為固定元素,與遍歷元素1進(jìn)行換位,剩余元素為空,此時(shí)排列為{3, 2, 1};
- 第14次遞歸調(diào)用(基于第13次):因?yàn)榈?4次遞歸調(diào)用時(shí)已經(jīng)選擇到了最后一個(gè)元素,遍歷結(jié)束,取得遍歷結(jié)束,取得第五個(gè)全排列結(jié)果{3, 2, 1}, 第14次遞歸結(jié)束;
- 因?yàn)榈?3次遞歸調(diào)用已經(jīng)遍歷結(jié)束,將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(1 <-> 1),得到開始前的排列{3, 2, 1};
- 第15次遞歸調(diào)用(基于第12次):第12次遞歸往下遍歷,將固定元素1與遍歷元素2進(jìn)行換位,此時(shí)排列為{3, 1, 2};
- 第16次遞歸調(diào)用(基于第15次):因?yàn)榈?6次遞歸調(diào)用時(shí)已經(jīng)選擇到了最后一個(gè)元素,遍歷結(jié)束,取得遍歷結(jié)束,取得第六個(gè)全排列結(jié)果{3, 1, 2}, 第16次遞歸結(jié)束;
- 因?yàn)榈?2次遞歸調(diào)用已經(jīng)遍歷結(jié)束,將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(1 <-> 3),得到開始前的排列{1, 2, 3};
- 因?yàn)榈?次遞歸調(diào)用已經(jīng)遍歷結(jié)束,將本次遞歸調(diào)用開始前進(jìn)行的換位元素返回原位置(1 <-> 1),得到開始前的排列{1, 2, 3};
遞歸算法處理
參數(shù):這里要求的是全排列的排列個(gè)數(shù),所以參數(shù)一定有元素?cái)?shù)組;要對(duì)整個(gè)數(shù)組進(jìn)行遍歷,那么就少不了下標(biāo)和范圍,所以這里的參數(shù)就是{數(shù)組、起始下標(biāo)、數(shù)組長(zhǎng)度}
返回值:這里不需要返回值,全排列個(gè)數(shù)通過全局變量進(jìn)行累加計(jì)算,若放在函數(shù)中,則每次都會(huì)被重置
上面一開始就說到了終止條件:當(dāng)遍歷到最后一個(gè)元素時(shí),即說明完成一個(gè)全排列
所以終止條件就是當(dāng) 下標(biāo)值 >= 數(shù)組長(zhǎng)度
由上面的模擬可以看到,每一次遞歸都是新的遍歷,所以有一個(gè)最外圍的循環(huán)遍歷邏輯,而每次遞歸前后都有換位操作,所以最終確定如下單層邏輯
🍔代碼🍔
void func(vector<int>& arr, int start, int len) {if (start >= len){count++;return;}for (i = start; i < len; i++){swap();func(arr, i + 1, len);swap();} }以上是我對(duì)全排列算法的粗糙理解,但是本題還有一個(gè)關(guān)鍵點(diǎn):考慮旋轉(zhuǎn)、鏡像后相同的算同一種
因?yàn)槿切斡腥齻€(gè)角,也就是說每個(gè)數(shù)字都能在三個(gè)角上出現(xiàn)一次,所以旋轉(zhuǎn)后相同算同一種的話,就需要將全排列總數(shù) / 3;
鏡像對(duì)CV戰(zhàn)士來說好理解,就是2分一模一樣的數(shù)據(jù),所以鏡像后算同一種的話,就需要將全排列總數(shù) / 2;
最終計(jì)算結(jié)果就是 全排列總數(shù) / 3 / 2,即總數(shù) / 6;
🍔總結(jié)🍔
遞歸算法一般都很難理順,自己一開始自己按原理推理的時(shí)候也一直弄亂,記不清當(dāng)前遞歸的條件。本題的關(guān)鍵就在于全排列算法和確定旋轉(zhuǎn)/鏡像的關(guān)系
總結(jié)
以上是生活随笔為你收集整理的【Code pratice】—— 纸牌三角形的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Symbol mc1000开发体验
- 下一篇: CentOS下torque集群配置(一)