【Leecode 随笔】C语言版看了不后悔系列持续更新中。。。

在这里插入图片描述

🌈你好呀!我是 山顶风景独好
🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然!😊
🌸愿您在此停留的每一刻,都沐浴在轻松愉悦的氛围中。
📖这里不仅有丰富的知识和趣味横生的内容等您来探索,更是一个自由交流的平台,期待您留下独特的思考与见解。🌟
🚀让我们一起踏上这段探索与成长的旅程,携手挖掘更多可能,共同进步!💪✨

第一题:最长递增子序列

题目描述:

给定一个整数数组 nums,找到其中最长严格递增子序列的长度。

示例输入:

nums = [10, 9, 2, 5, 3, 7, 101, 18]
输出: 4
解释: 最长递增子序列是 [2, 3, 7, 101],长度为 4。
nums = [0, 1, 0, 3, 2, 3]
输出: 4
解释: 最长递增子序列是 [0, 1, 2, 3],长度为 4。

解题思路:

这是一个经典的动态规划问题。我们可以使用一个数组 dp,其中 dp[i] 表示以 nums[i] 结尾的最长递增子序列的长度。初始时,dp[i] 被设置为 1,因为每个元素都可以成为一个长度为 1 的子序列。然后,我们遍历 nums 数组,对于每个 nums[i],再遍历它之前的所有元素 nums[j](j 从 0 到 i-1),如果 nums[i] > nums[j],则更新 dp[i] 为 dp[i] 和 dp[j] + 1 中的较大值。最终,dp 数组中的最大值即为所求。

示例代码:

#include <stdio.h>  
  
int lengthOfLIS(int* nums, int numsSize) {  
    if (numsSize == 0) return 0;  
      
    int dp[numsSize];  
    for (int i = 0; i < numsSize; i++) {  
        dp[i] = 1; // 每个元素至少可以作为长度为1的子序列  
    }  
      
    int maxLength = 1;  
    for (int i = 1; i < numsSize; i++) {  
        for (int j = 0; j < i; j++) {  
            if (nums[i] > nums[j]) {  
                dp[i] = (dp[i] > dp[j] + 1) ? dp[i] : dp[j] + 1;  
            }  
        }  
        maxLength = (maxLength > dp[i]) ? maxLength : dp[i];  
    }  
      
    return maxLength;  
}  
  
int main() {  
    int nums1[] = {10, 9, 2, 5, 3, 7, 101, 18};  
    int numsSize1 = sizeof(nums1) / sizeof(nums1[0]);  
    printf("Length of LIS in nums1: %d\n", lengthOfLIS(nums1, numsSize1));  
      
    int nums2[] = {0, 1, 0, 3, 2, 3};  
    int numsSize2 = sizeof(nums2) / sizeof(nums2[0]);  
    printf("Length of LIS in nums2: %d\n", lengthOfLIS(nums2, numsSize2));  
      
    return 0;  
}

深入剖析:

时间复杂度:O(n^2),因为有两个嵌套的循环。
空间复杂度:O(n),因为使用了一个额外的 dp 数组来存储以每个元素结尾的最长递增子序列的长度。
优化:可以使用二分查找进一步优化到 O(n log n),但这需要更复杂的实现。

第二题:不同的二叉搜索树

题目描述:

给定一个正整数 n,求有多少种不同的二叉搜索树的拓扑结构,其节点值从 1 到 n 互不相同。

示例输入:

n = 3
输出: 3
n = 1
输出: 1

解题思路:

这是一个动态规划问题,可以用卡塔兰数(Catalan number)来求解。对于给定的 n,设 G(n) 为可能的二叉搜索树的数量。如果我们选择 i 作为根节点(1 <= i <= n),则左子树包含 i-1 个节点,右子树包含 n-i 个节点。因此,G(n) 可以通过以下递推关系计算:
G(n)=∑
i=1
n
​G(i−1)×G(n−i)
边界条件是 G(0) = 1 和 G(1) = 1。

示例代码:

#include <stdio.h>  
  
int numTrees(int n) {  
    if (n <= 1) return 1;  
      
    int dp[n + 1];  
    dp[0] = 1;  
    dp[1] = 1;  
      
    for (int i = 2; i <= n; i++) {  
        dp[i] = 0;  
        for (int j = 1; j <= i; j++) {  
            dp[i] += dp[j - 1] * dp[i - j];  
        }  
    }  
      
    return dp[n];  
}  
  
int main() {  
    int n1 = 3;  
    printf("Number of unique BSTs for n=%d: %d\n", n1, numTrees(n1));  
      
    int n2 = 1;  
    printf("Number of unique BSTs for n=%d: %d\n", n2, numTrees(n2));  
      
    return 0;  
}

深入剖析:

时间复杂度:O(n^2),因为有两个嵌套的循环。
空间复杂度:O(n),因为使用了一个额外的 dp 数组来存储每个 n 对应的不同二叉搜索树的数量。

第三题:最大正方形

题目描述:

在一个2D二进制矩阵中,找到只包含1的最大正方形的边长。

示例输入:

matrix = [ [“1”,“0”,“1”,“0”,“0”], [“1”,“0”,“1”,“1”,“1”], [“1”,“1”,“1”,“1”,“1”], [“1”,“0”,“0”,“1”,“0”] ]
输出: 2
解释: 最大正方形边长为2,对应的正方形为:
1 1
1 1
matrix = [ [“0”,“1”,“1”,“0”,“1”], [“1”,“1”,“0”,“1”,“1”], [“1”,“1”,“1”,“1”,“1”], [“0”,“1”,“1”,“1”,“1”], [“1”,“1”,“1”,“1”,“1”] ]
输出: 4
解释: 最大正方形边长为4,对应的正方形为:
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1

解题思路:

这是一个动态规划问题。我们使用一个二维数组 dp,其中 dp[i][j] 表示以 (i, j) 为右下角的最大正方形的边长。如果 matrix[i][j] 是 ‘1’,则 dp[i][j] 的值可以通过它左边、上边和左上对角线的最小值加1得到。即:
dp[i][j]=min(dp[i−1][j],dp[i][j−1],dp[i−1][j−1])+1
边界条件是 dp[i][0] 和 dp[0][j] 取决于 matrix 的第一行和第一列。

示例代码:

#include <stdio.h>  
#include <string.h>  
#include <math.h> // 引入头文件以使用fmin函数  
  
#define MAX 100  
  
int maximalSquare(char matrix[MAX][MAX], int matrixSize, int matrixColSize) {  
    if (matrixSize == 0 || matrixColSize == 0)   
        return 0;  
  
    int dp[MAX][MAX] = {0};  
    int maxSquareLen = 0;  
  
    // 初始化第一列  
    for (int i = 0; i < matrixSize; i++) {  
        dp[i][0] = matrix[i][0] - '0'; // 将字符转换为整数  
        maxSquareLen = (dp[i][0] > maxSquareLen) ? dp[i][0] : maxSquareLen;  
    }  
  
    // 初始化第一行  
    for (int j = 0; j < matrixColSize; j++) {  
        dp[0][j] = matrix[0][j] - '0'; // 将字符转换为整数  
        maxSquareLen = (dp[0][j] > maxSquareLen) ? dp[0][j] : maxSquareLen;  
    }  
  
    // 动态规划计算最大正方形边长  
    for (int i = 1; i < matrixSize; i++) {  
        for (int j = 1; j < matrixColSize; j++) {  
            if (matrix[i][j] == '1') {  
                dp[i][j] = 1 + fmin(fmin(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]);  
                maxSquareLen = (dp[i][j] > maxSquareLen) ? dp[i][j] : maxSquareLen;  
            }  
        }  
    }  
  
    return maxSquareLen;  
}  
  
int main() {  
    // 第一个矩阵  
    char matrix1[5][5] = {  
        "10100",  
        "10111",  
        "11111",  
        "10010"  
    };  
    int matrixSize1 = 4;  
    int matrixColSize1 = 5;  
    printf("Maximal square length in matrix1: %d\n", maximalSquare(matrix1, matrixSize1, matrixColSize1));  
  
    // 第二个矩阵  
    char matrix2[6][6] = {  
        "01101",  
        "11011",  
        "11111",  
        "01111",  
        "11111"  
    };  
    int matrixSize2 = 5;  
    int matrixColSize2 = 5;  
    printf("Maximal square length in matrix2: %d\n", maximalSquare(matrix2, matrixSize2, matrixColSize2));  
  
    return 0;  
}

深入剖析:

  • 时间复杂度:O(m * n),其中 m 是矩阵的行数,n 是矩阵的列数。因为需要遍历整个矩阵一次来计算 dp 数组。
  • 空间复杂度:O(m * n),因为使用了一个与输入矩阵大小相同的 dp 数组来存储以每个位置为右下角的最大正方形的边长。

✨ 这就是今天要分享给大家的全部内容了,我们下期再见!😊
🏠 我在CSDN等你哦!我的主页😍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山顶风景独好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值