tree traversal (樹的遍歷) - 前序遍歷 (preorder traversal) - 對稱二叉樹

tree traversal (樹的遍歷) - 前序遍歷 (preorder traversal) - 對稱二叉樹

symmetric [sɪ'metrɪk]:adj. 對稱的,勻稱的

1. 二叉搜索樹 (binary search tree) - 對稱二叉樹

  1. 如果所給的根節點爲空,那麼它是對稱二叉樹。
  2. 如果所給的根節點不爲空,當它的左子樹與右子樹對稱時,那麼它是對稱二叉樹。
  3. 如果左子樹的左孩子與右子樹的右孩子對稱,左子樹的右孩子與右子樹的左孩子對稱,那麼左子樹和右子樹對稱。
  4. 分析可以遞歸的點 (遞歸點):判斷左子樹與右子樹對稱的條件時,其跟兩樹的孩子的對稱情況有關係。函數 function_B (左樹, 右樹) 功能是返回是否對稱。
    函數 function_B (左樹, 右樹):左樹節點值等於右樹節點值且 函數function_B (左樹的左子樹, 右樹的右子樹)函數 function_B (左樹的右子樹, 右樹的左子樹) 均爲真才返回真。

1.1 遞歸

如果一個樹的左子樹與右子樹鏡像對稱,那麼這個樹是對稱的。

在這裏插入圖片描述

如果同時滿足下面的條件,兩個樹互爲鏡像:

  1. 它們的兩個根結點具有相同的值。
  2. 左樹的左節點 == 右樹的右節點
  3. 左樹的右節點 == 右樹的左節點

就像人站在鏡子前審視自己那樣,鏡中的反射與現實中的人具有相同的頭部,但反射的右臂對應於人的左臂,反之亦然。

在這裏插入圖片描述

  • 時間複雜度:O(n)。遍歷整個輸入樹一次,總的運行時間爲 O(n),其中 n 是樹中結點的總數。
  • 空間複雜度:遞歸調用的次數受樹的高度限制。在最糟糕情況下,樹是線性的,其高度爲 O(n)。在最糟糕的情況下,由棧上的遞歸調用造成的空間複雜度爲 O(n)

1.2 迭代

除了遞歸的方法外,也可以利用兩個棧 (stack) 進行迭代。兩個棧 (stack) 初始化爲 root->leftroot->right。每次提取兩個結點並比較它們的值。然後,將兩個結點的左右子結點按相反的順序插入棧 (stack) 中。當隊列爲空或者檢測到樹不對稱 (即從隊列中取出兩個不相等的連續結點) 時,該算法結束。

要判斷二叉樹是不是對稱,只需要訪問鏡像元素值是否相等,即對左右子樹做相反順序的遍歷即可。

根節點的左子樹進行前序遍歷 [DLR,首先訪問根結點,然後前序遍歷其左子樹,最後前序遍歷其右子樹],同時對根節點的右子樹進行 [DRL,首先訪問根結點,然後前序遍歷其右子樹,最後前序遍歷其左子樹] 遍歷。

首先查看左右子樹的當前節點,然後對於左子樹採用 DLR 方式遍歷的同時,對於右子樹採用 DRL 方式遍歷,這樣同時訪問的兩個結點是鏡像位置的兩個結點,若結點值不同,則不對稱。

2. 對稱二叉樹

給定一個二叉樹,檢查它是否是鏡像對稱的。

例如二叉樹 [1, 2, 2, 3, 4, 4, 3] 是對稱的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

但是下面這個 [1, 2, 2, null, 3, null, 3] 則不是鏡像對稱的:

    1
   / \
  2   2
   \   \
   3    3

遞歸和迭代兩種方法解決問題。

//============================================================================
// Name        : preorder traversal
// Author      : Yongqiang Cheng
// Version     : Feb 22, 2020
// Copyright   : Copyright (c) 2020 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================

/*
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

bool isSymmetric(struct TreeNode* root)
{
	int front_l = 0, front_r = 0;
	struct TreeNode* STACK_L[512] = { NULL };
	struct TreeNode* STACK_R[512] = { NULL };
	struct TreeNode* pnode = NULL;
	struct TreeNode* qnode = NULL;

	if (NULL == root)
	{
		return true;
	}

	front_l = -1;
	front_r = -1;

	STACK_L[++front_l] = root->left;
	STACK_R[++front_r] = root->right;

	while (front_l >= 0)
	{
		pnode = STACK_L[front_l];
		qnode = STACK_R[front_r];
		front_l--;
		front_r--;

		if ((NULL == pnode) && (NULL == qnode))
		{
			continue;
		}

		if ((NULL == pnode) || (NULL == qnode))
		{
			return false;
		}

		if (pnode->val != qnode->val)
		{
			return false;
		}

		++front_l;
		STACK_L[front_l] = pnode->right;
		++front_l;
		STACK_L[front_l] = pnode->left;

		++front_r;
		STACK_R[front_r] = qnode->left;
		++front_r;
		STACK_R[front_r] = qnode->right;
	}

	return true;
}

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

//============================================================================
// Name        : preorder traversal
// Author      : Yongqiang Cheng
// Version     : Feb 22, 2020
// Copyright   : Copyright (c) 2020 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================

/*
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

bool isSymmetric(struct TreeNode* root)
{
	int front_l = 0, front_r = 0;
	struct TreeNode* STACK_L[512] = { NULL };
	struct TreeNode* STACK_R[512] = { NULL };
	struct TreeNode* pnode = NULL;
	struct TreeNode* qnode = NULL;

	if (NULL == root)
	{
		return true;
	}

	front_l = -1;
	front_r = -1;

	STACK_L[++front_l] = root->left;
	STACK_R[++front_r] = root->right;

	while (front_l >= 0)
	{
		pnode = STACK_L[front_l];
		qnode = STACK_R[front_r];
		front_l--;
		front_r--;

		if ((NULL == pnode) && (NULL == qnode))
		{
			continue;
		}

		if ((NULL == pnode) || (NULL == qnode))
		{
			return false;
		}

		if (pnode->val != qnode->val)
		{
			return false;
		}

		STACK_L[++front_l] = pnode->right;
		STACK_L[++front_l] = pnode->left;

		STACK_R[++front_r] = qnode->left;
		STACK_R[++front_r] = qnode->right;
	}

	return true;
}

References

https://leetcode-cn.com/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章