CSDN竞赛63期题解
发布人:shili8
发布时间:2024-12-26 16:24
阅读次数:0
**CSDN竞赛63期题解**
本期题目为:
**[63期] 最长上升子序列 II**
给定一个长度为 n 的整数数组 arr,要求找到最长上升子序列(LIS)的长度。
注意:这个问题的难度比之前的版本高,因为我们需要考虑到子序列中可以出现重复元素的情况。
**题解**
###1. 动态规划我们首先尝试使用动态规划来解决这个问题。我们定义一个一维数组 dp,长度为 n+1,dp[i] 表示 arr 中前 i 个数字的最长上升子序列的长度。
cppint findLIS(int* arr, int n) { int dp[n +1]; for (int i =0; i <= n; i++) { dp[i] =1; } for (int i =1; i <= n; i++) { for (int j =0; j < i; j++) { if (arr[i -1] > arr[j -1]) { dp[i] = max(dp[i], dp[j] +1); } } } int maxLIS =0; for (int i =0; i <= n; i++) { maxLIS = max(maxLIS, dp[i]); } return maxLIS; }
###2. 二分查找我们可以使用二分查找来找到 arr 中第一个大于等于给定值的元素。
cppint findFirstGreater(int* arr, int n, int target) { int left =0; int right = n -1; while (left <= right) { int mid = left + (right - left) /2; if (arr[mid] >= target) { right = mid -1; } else { left = mid +1; } } return left == n ? -1 : arr[left]; }
###3. 最长上升子序列 II我们可以使用二分查找来找到 arr 中第一个大于等于给定值的元素,然后将该元素添加到最长上升子序列中。
cppint findLISII(int* arr, int n) { int dp[n +1]; for (int i =0; i <= n; i++) { dp[i] =1; } for (int i =1; i <= n; i++) { int target = arr[i -1]; int index = findFirstGreater(arr, n, target); if (index == -1) { dp[i] =1; } else { dp[i] = dp[index] +1; } } int maxLIS =0; for (int i =0; i <= n; i++) { maxLIS = max(maxLIS, dp[i]); } return maxLIS; }
###4. 测试我们可以使用以下测试用例来测试我们的函数。
cppint main() { int arr[] = {10,22,9,33,21,50,41,60}; int n = sizeof(arr) / sizeof(arr[0]); printf("最长上升子序列的长度:%d ", findLISII(arr, n)); return0; }
###5. 结论我们可以使用动态规划和二分查找来解决这个问题。我们的函数 `findLISII` 可以找到最长上升子序列的长度。
**注释**
* 我们定义了一个一维数组 dp,长度为 n+1,dp[i] 表示 arr 中前 i 个数字的最长上升子序列的长度。
* 我们使用二分查找来找到 arr 中第一个大于等于给定值的元素。
* 我们将该元素添加到最长上升子序列中。
* 我们可以使用以下测试用例来测试我们的函数。
**参考**
* [63期] 最长上升子序列 II* 动态规划* 二分查找