leetcode102题C语言思路

该博客介绍了如何使用C语言解决LeetCode第102题,即二叉树的层次遍历。通过`max_depth`计算树的最大深度,`calcColumnSizes`计算每一层的节点数,以及`fetch_result`获取每一层的节点值。通过递归遍历二叉树,存储不同层次的节点数量和值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

int** levelOrder(struct TreeNode* root, int** columnSizes, int* returnSize) //从函数的接口分析,root为传入参数,为树的根节点。int** columnSizes, int* returnSize是传出参数,retrunSize是树的深度,columnSizes是数组,是每行的节点的个数。

因为C不能传出多个参数,因此需要保留改变值就必须参数实参,即传入地址来达到修改的目的。也可以把他们看为一个数组,相当于取出数组中的第一个元素。
首先需要得到数的深度,这个用递归很容易得到
int max_depth(struct TreeNode* root) {
    if (root == NULL) return 0;
    int ld = max_depth(root->left);
    int rd = max_depth(root->right);
    return (ld > rd ? ld : rd) + 1;
}


k为深度,对于树的遍历时,设置它可以让程序更加合理,这个技巧需要较多的联系后才能理解

然后需要遍历一遍树,找到每一层右多少个节点,这是为了给二维数组每一个位置申请空间的。
void calcColumnSizes(struct TreeNode *root, int k, int *arr) {
    if (root == NULL) return ;
    arr[k] += 1;
    calcColumnSizes(root->left, k + 1, arr);
    calcColumnSizes(root->right, k + 1, arr);
    return ;
}//也是通过递归实现的
void fetch_result(struct TreeNode *root, int k, int *ind, int **ret) {
    if (root == NULL) return ;
    ret[k][ind[k]++] = root->val;
    fetch_result(root->left, k + 1, ind, ret);
    fetch_result(root->right, k + 1, ind, ret);
    return ;
}//再次遍历一遍,记录每一层的节点

int** levelOrder(struct TreeNode* root, int** columnSizes, int* returnSize) {
    int depth = max_depth(root);
    int *sizes = (int *)calloc(depth, sizeof(int));
    calcColumnSizes(root, 0, sizes);    
    int **ret = (int **)malloc(sizeof(int *) * depth);
    for (int i = 0; i < depth; i++) {
        ret[i] = (int *)malloc(sizeof(int) * sizes[i]);
        sizes[i] = 0;//将size设为0可以节省一个数组空间
    }
    fetch_result(root, 0, sizes, ret);
    *columnSizes = sizes;
    *returnSize = depth;
    return ret;
}

//整体实现
int max_depth(struct TreeNode* root) {
if (root == NULL) return 0;
int ld = max_depth(root->left);
int rd = max_depth(root->right);
return (ld > rd ? ld : rd) + 1;
}

void calcColumnSizes(struct TreeNode *root, int k, int *arr) {
if (root == NULL) return ;
arr[k] += 1;
calcColumnSizes(root->left, k + 1, arr);
calcColumnSizes(root->right, k + 1, arr);
return ;
}

void fetch_result(struct TreeNode *root, int k, int *ind, int **ret) {
if (root == NULL) return ;
ret[k][ind[k]++] = root->val;
fetch_result(root->left, k + 1, ind, ret);
fetch_result(root->right, k + 1, ind, ret);
return ;
}

int** levelOrder(struct TreeNode* root, int** columnSizes, int* returnSize) {
int depth = max_depth(root);
int sizes = (int )calloc(depth, sizeof(int));
calcColumnSizes(root, 0, sizes);
int ret = (int )malloc(sizeof(int ) depth);
for (int i = 0; i < depth; i++) {
ret[i] = (int )malloc(sizeof(int) sizes[i]);
sizes[i] = 0;
}
fetch_result(root, 0, sizes, ret);
*columnSizes = sizes;
*returnSize = depth;
return ret;
}
“`

目描述: 给定一个没有重复数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 解思路: 这是一个典型的回溯算法的问,我们可以通过递归的方式实现。我们先固定一个数,再递归求解剩下的数的排列,最后再将固定的数和递归求解的结果合并。 代码实现: void backtrack(int* nums, int numsSize, int** result, int* returnSize, int index) { if (index == numsSize) { // 递归结束 result[*returnSize] = (int *)malloc(numsSize * sizeof(int)); // 为result分配空间 memcpy(result[*returnSize], nums, numsSize * sizeof(int)); // 将nums复制到result中 (*returnSize)++; // 返回结果数量自增1 return; } for (int i = index; i < numsSize; i++) { // 遍历数组 // 交换元素 int temp = nums[index]; nums[index] = nums[i]; nums[i] = temp; // 递归 backtrack(nums, numsSize, result, returnSize, index + 1); // 恢复原数组 temp = nums[index]; nums[index] = nums[i]; nums[i] = temp; } } int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) { int count = 1; for (int i = 2; i <= numsSize; i++) { count *= i; // 计算排列的总数 } int** result = (int **)malloc(count * sizeof(int *)); *returnColumnSizes = (int *)malloc(count * sizeof(int)); *returnSize = 0; backtrack(nums, numsSize, result, returnSize, 0); for (int i = 0; i < *returnSize; i++) { (*returnColumnSizes)[i] = numsSize; } return result; }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值