URL
题目
分析
证明:http://courses.csail.mit.edu/6.046/fall01/handouts/ps9sol.pdf
源码
工程结构
.
└── main_310.c
源码文件
/* main_310.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node {
int val;
struct list_node * next;
}LIST_NODE;
int * find_mid_height_trees(int n , int ** edges ,
int edges_size ,
int * return_size)
{
int *res = NULL;
if (n == 1){
res = (int *)malloc(sizeof(int));
*res = 0;
*return_size = 1;
return res;
}
/*
申请n个节点的list
申请n个节点的degree
初始化每个节点的next为NULL
*/
struct list_node ** adj = (struct list_node **)malloc(sizeof(struct list_node *) * n); // leetcode 官解给的强转类型是(struct list_node *) , emm....如果是我错了烦请告知一下原因
int *degree = (int *)malloc(sizeof(int) * n);
memset(degree, 0, sizeof(int) * n);
for (int i = 0; i < edges_size; ++i){
adj[i] = NULL;
}
/*
定义u,v为节点列表中的下标
申请node,赋值val,next指向节点列表中下表为u的节点,同时将节点列表中下标为u的指针指向当前node地址
申请node,赋值val,next指向节点列表中下表为v的节点,同时将节点列表中下标为v的指针指向当前node地址
*/
for (int i = 0; i < edges_size; ++i){
int u = edges[i][0];
int v = edges[i][1];
struct list_node *node = (struct list_node *)malloc(sizeof(struct list_node));
node->val = u;
node->next = adj[v];
adj[v] = node;
node = (struct list_node *)malloc(sizeof(struct list_node));
node->val = v;
node->next = adj[u];
adj[u] = node;
degree[u]++;
degree[v]++; // 20220407 FIX
}
/*
申请一个大小为n的队列,用于存储degree为1的节点下标,
遍历degree数组,找到度为1的节点下标,并将下标存储到queue队列中,同时queue尾++,便于计算queue元素个数
*/
int * queue = (int *)malloc(sizeof(int) * n);
int head = 0;
int tail = 0;
for (int i = 0; i < n; ++i){
if(degree[i] == 1){
queue[tail++] = i;
}
}
/*
将queue外的节点数记为remain_nodes,即remain_nodes == n - queue中节点个数(变化值),即:remain_nodes = n;sz = tail - head;remain_nodes -= sz;
遍历queue中节点,将该节点所有子节点的degree--,将最后度为1的节点再加到queue中,将queue尾++,即将合法节点val记录到queue[tail]处 ;head++,到最后queue中[head,tail]的节点都为合法值
*/
int remain_nodes = n;
while(remain_nodes > 2){
int sz = tail - head;
remain_nodes -= sz;
for (int i = 0; i < sz; ++i){
int curr = queue[head++];
struct list_node * node = adj[curr];
while(node){
int v = node->val;
degree[v]--;
if (degree[v] == 1){
queue[tail++] = v;
}
node = node->next;
}
}
}
/*
remain_nodes即为所有合法节点的数量,赋值return_size返回合法节点的个数,
将queue中[head,tail]的节点赋值给res,返回res数组
*/
res = (int *)malloc(sizeof(int) * remain_nodes);
*return_size = remain_nodes;
int pos = 0;
while (head != tail){
res[pos++] = queue[head++];
}
free(queue);
free(degree);
for (int i = 0; i < n; ++i){
struct list_node * node = adj[i];
while(node){
struct list_node * curr = node;
node = curr->next;
free(curr);
}
}
free(adj);
return res;
}
int main()
{
#if 0
int n = 4;
int edges_arr[][2] = {{1,0},{1,2},{1,3}};
#else
int n = 6;
int edges_arr[][2] = {{3,0},{3,1},{3,2},{3,4},{5,4}};
#endif
/* */
int edges_size = sizeof(edges_arr)/sizeof(edges_arr[0]);
int ** edges = (int **)malloc(sizeof(int *) * (edges_size * 2));
for (int i = 0; i < edges_size; ++i){
edges[i] = (int *)malloc(sizeof(int) * 2);
edges[i][0] = edges_arr[i][0];
edges[i][1] = edges_arr[i][1];
}
/* */
int ret_size = 0;
int * ret_node = find_mid_height_trees(n, edges, edges_size, &ret_size);
for(int i = 0; i < ret_size; ++i){
printf("root node = %d\n",ret_node[i]);
}
/* */
for (int i = 0; i < edges_size; ++i){
free(edges[i]);
}
free(edges);
free(ret_node);
return 0;
}
LOG参考
root node = 1
root node = 3
root node = 4
源码概述
- 看源码,不赘述
小结
- 一个数学证明是算法前提
- 将degree做自减操作,得到需要的度
- 用 u,v 表示前节点值、后节点地址