[leetcode日記]102:二叉樹層序遍歷

題目

給你一個二叉樹,請你返回其按 層序遍歷 得到的節點值。 (即逐層地,從左到右訪問所有節點)。

示例: 二叉樹:[3,9,20,null,null,15,7],

      3  
     / \  
   9  20
      /  \    
     15   7

返回其層次遍歷結果:

[ [3], [9,20], [15,7] ]

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

分析

關於層序遍歷,可以設計一個隊列。
主要思路:首先進隊一個“隔板”,然後根節點入隊。然後出隊一個元素,若它是“隔板”就申請一個新的數組空間並進隊一個“隔板”。如果它有左右子節點就讓它子節點入隊。如此循環,直到隊列中連着兩次訪問到“隔板”。

代碼

#define ARRAY_MAX 1000

typedef struct QueueNode {
    struct TreeNode *data;
    struct QueueNode *next;
} QueueNode_t;

typedef struct LinkQueue {
    int count;
    QueueNode_t *front;
    QueueNode_t *rear;
} LinkQueue_t;

int initQueue(LinkQueue_t *queue) {
    queue->front = queue->rear = malloc(sizeof(QueueNode_t));
    if (NULL == queue->front)
        return -1;
    queue->front->next = NULL;
    queue->count = 0;
    return 0;
}

int enqueue(LinkQueue_t *queue, struct TreeNode *data) {
    QueueNode_t *newNode = malloc(sizeof(QueueNode_t));
    if (NULL == newNode) {
        return -1;
    }

    newNode->data = data;
    newNode->next = NULL;
    queue->rear->next = newNode;
    queue->rear = newNode;
    queue->count++;

    return 0;
}

int dequeue(LinkQueue_t *queue, struct TreeNode **data) {
    if (queue->front == queue->rear) {
        return -1;
    }

    QueueNode_t *denode = queue->front->next;
    *data = denode->data;
    queue->front->next = denode->next;

    if (denode == queue->rear) {
        queue->rear = queue->front;
    }

    free(denode);
    queue->count--;
    return 0;
}

void destroyQueue(LinkQueue_t *queue) {
    /*q->front 指向頭node, queue->rear指向下一個節點,這裏當臨時指針用*/
    while (queue->front) {
        queue->rear = queue->front->next;
        free(queue->front);
        queue->front = queue->rear;
    }
}

int emptyQueue(LinkQueue_t *queue) {
    return queue->front == queue->rear ? 1 : 0;
}

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 * 注:levelOrder返回的是一個指針數組,每個成員存儲指向當前下標所在層的所有節點(另一個數組)。returnSize爲levelOrder數組的大小。
 *     returnColumnSizes指向一個數組,每個成員對應levelOrder裏相同下標指向的一維數組的大小。
 */
int **levelOrder(struct TreeNode *root, int *returnSize, int **returnColumnSizes) {
    if (NULL == root){
        *returnSize = 0;
        return NULL;
    }

    int level = 0, i = 0, cnt = 0;
    int **retArray = malloc(ARRAY_MAX * sizeof(int *));
    struct TreeNode *data = NULL;

    *returnColumnSizes = malloc(ARRAY_MAX * sizeof(int));
    
    LinkQueue_t queue;
    initQueue(&queue);
    enqueue(&queue, root);
    
    while (!emptyQueue(&queue)) {
        cnt = queue.count;
        retArray[level] = malloc(sizeof(int) * cnt);
        for (i = 0; i < cnt; i++) {
            dequeue(&queue, &data);
            retArray[level][i] = data->val;

            if (data->left)
                enqueue(&queue, data->left);
            if (data->right)
                enqueue(&queue, data->right);
        }
        (*returnColumnSizes)[level] = cnt;

        level++;
    }
    *returnSize = level;
     destroyQueue(&queue);

    return retArray;
}

運行結果

在這裏插入圖片描述

作弊的代碼

當然也可以實現判斷一下樹總共有多少節點,不過這種做法有點像作弊。不是很推薦。

 // 這樣寫死是不推薦的操作。可以用在開頭的時候計算這棵樹總共有多少個節點。
struct TreeNode* queue[10000] = {0};


int maxDepth(struct TreeNode* root){
    //查找最深的節點,並返回層數
    int left_depth = 0;
    int right_depth = 0;
    if (root == NULL) {
        return 0;
    }
    left_depth = maxDepth(root->left);
    right_depth = maxDepth(root->right);
    return left_depth > right_depth ? left_depth + 1 : right_depth + 1;

}


/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes){

	int tail = 0;
	int front = 0;
    if (root == NULL) {
        *returnSize = 0;
        *returnColumnSizes = NULL;
        return NULL;
    }



	int depth = maxDepth(root);
	*returnSize = depth;

	int* columarry = (int*)malloc(depth * sizeof(int));
    int* columarrytmp = columarry;
    
	int** result = (int**)malloc(depth * sizeof(int *));
	int** resulttmp = result;

	queue[tail] = root;
	front += 1;
	while (front != tail) {
		int num = front - tail;
		*(columarrytmp++) = num;
		
		int * arry = malloc(num * sizeof(int));
        int * arrytmp = arry;
        
		for (int i = 0; i < num; i++) {
			struct TreeNode* tmp = queue[tail];
			*(arrytmp++) = tmp->val;

			tail++;
			if (tmp->left != NULL) {
				queue[front] = tmp->left;
				front++;
			}
			if (tmp->right != NULL) {
				queue[front] = tmp->right;
				front++;
			}
		}
		*(resulttmp++) = arry;
	}

	*returnColumnSizes = columarry;
	return result;
}

運行結果

在這裏插入圖片描述

這道題目我在阿里雲面試的時候遇到過類似的:利用非遞歸手段遍歷一棵二叉樹。當時我也是採用了隊列的方式。

我現在因爲馬上就要去阿里雲實習了,有好多東西是需要我惡補的。所以我打算暫時少更一點leetcode日記了,可能要從日更變成周更左右……不過影響不大嘿嘿。
我出於熟悉java的目的(沒錯我今天剛開始學習java,我會拿一些以前C做過過的題目練練手)。

感謝大家的瀏覽和點贊。

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