摺紙問題 C++實現

題目描述:

把紙條豎着放在桌面上,然後從紙條的下邊向上對摺,壓出摺痕後再展開。如果每次都從下邊向上對摺,對摺N次。

我們規定,對於每條摺痕,如果突起的方向指向紙條的背面,那麼這條摺痕叫做“下”摺痕 ;相反,突起的方向指向紙條正面的摺痕叫做“上”摺痕。

請從上到下打印所有摺痕的方向。


分析:

當紙條從下向上對摺一次後打開,有一條摺痕,向下,記爲0。

繼續再向上對摺一次,打開後,在原來0號摺痕上下各出現一條新摺痕,上邊摺痕向下,記爲1號。下邊摺痕向上,記爲2號。

繼續再向上對摺一次,打開後,在1號摺痕和2號摺痕上下各出現一條新摺痕,仍舊上邊向下,下邊向上。


結論:

由以上分析可以看出,對於每一條摺痕,其上下新產生的摺痕必是:上邊的那條向下,下邊的那條向上。

這樣看來,按照摺痕產生的先後順序,其實是滿二叉樹結構。該二叉樹的特點是:根結點是下,每一個節點的左子結點是下,右子結點是上。該二叉樹的中序遍歷即爲答案。


實現:

我們用一個假想的一維數組來模擬這個滿二叉樹,如果摺疊N次,那麼共有2N-1條摺痕,也就是說,這棵想象中的滿二叉樹,有2N-1個結點。從1開始按層次遍歷標號各結點。顯然,除根結點外,偶數號結點均爲左結點,奇數號結點均爲右結點。也就是說,遇到偶數,就輸出Down,遇到奇數,就輸出Up.

迭代來實現二叉樹的中序遍歷即可搞定。

函數的形參 Counter就是摺紙的次數

#include <iostream>
#include <cmath>
#include <stack>
//使用中序遍歷滿二叉樹
//這裏的完全二叉樹(其實是滿二叉樹)用數組表示
void printLineUpDown(int Counter)
{
	if(Counter < 1)
        return;
	else if(1 == Counter)
    {
        endl(std::cout << "Down");
        return;
    }

	unsigned NodeCount = pow(2, Counter) - 1;
	std::stack<unsigned int> s;
	unsigned int tree = 1;
	while(tree <= NodeCount || !s.empty())
	{
		while(tree <= NodeCount)
		{
			s.push(tree);
			tree *= 2;
		}

		tree = s.top();
		s.pop();

		if(0 == tree%2 || 1 == tree)
			endl(std::cout << "Down");
		else
			endl(std::cout << "Up");
        //因爲中序遍歷,只要訪問了當前結點,那麼其左子樹已訪問完畢
        //讓tree指向當前結點的右子結點
		tree *= 2;
		tree++;
	}
}

由上述代碼分析,壓棧的最大深度即爲該二叉樹的高度,也就是摺紙的次數,故該算法空間複雜度爲O(logN),時間複雜度爲O(N)。




發佈了109 篇原創文章 · 獲贊 49 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章