文章目录
🌈你好呀!我是 山顶风景独好
🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然!😊
🌸愿您在此停留的每一刻,都沐浴在轻松愉悦的氛围中。
📖这里不仅有丰富的知识和趣味横生的内容等您来探索,更是一个自由交流的平台,期待您留下独特的思考与见解。🌟
🚀让我们一起踏上这段探索与成长的旅程,携手挖掘更多可能,共同进步!💪✨
第一题:最长递增子序列
题目描述:
给定一个整数数组 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等你哦!我的主页😍