当前位置: 首页 > wzjs >正文

重庆网页设计网站关键词百度自然排名优化

重庆网页设计,网站关键词百度自然排名优化,浙江网站建设情况分析,wordpress一登录就错位文章目录 前言一、普通动态规划(DP)求解LIS1.DP思路2.DP的状态定义与转移方程3.DP的时间与空间复杂度4.DP代码实现5.DP的图文示例 二、贪心 二分查找求解LIS1.思路分析2.贪心 二分的时间与空间复杂度 三. 模板题讲解1.洛谷B3637 最长上升子序列1.dp写法…

文章目录

  • 前言
  • 一、普通动态规划(DP)求解LIS
    • 1.DP思路
    • 2.DP的状态定义与转移方程
    • 3.DP的时间与空间复杂度
    • 4.DP代码实现
    • 5.DP的图文示例
  • 二、贪心 + 二分查找求解LIS
    • 1.思路分析
    • 2.贪心 + 二分的时间与空间复杂度
  • 三. 模板题讲解
    • 1.洛谷B3637 最长上升子序列
      • 1.dp写法
      • 2.贪心+二分写法
    • 2.洛谷P3902 递增
      • 1.贪心+二分写法
  • 四.练习题
    • 1.洛谷P1091 [NOIP 2004 提高组] 合唱队形
      • 1.思路分析
    • 2.洛谷P1020 [NOIP 1999 提高组] 导弹拦截
      • 1.思路分析
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

在开始讲解算法之前,我们先明确LIS的定义

子序列:从一个序列中挑选一些元素(不要求连续),但必须保持原始相对顺序。例如,对于序列 [10, 9, 2, 5],[10, 2] 和 [9, 5] 都是子序列。
严格递增:子序列中的每个元素必须比前一个元素严格大。例如,[1, 3, 5] 是严格递增的,但 [1, 3, 3] 不是(因为有相等的情况)。
LIS问题:给定一个序列,找出其中最长的严格递增子序列的长度
示例:

输入序列:[10, 9, 2, 5, 3, 7, 101, 18]
可能的递增子序列:
[10, 101](长度 2)
[2, 5, 7, 101](长度 4)
[2, 3, 7, 18](长度 4)
答案:最长递增子序列的长度为 4。
接下来,我们将详细介绍两种方法来解决这个问题
并且给出多道例题进行讲解


提示:以下是本篇文章正文内容,下面案例可供参考

一、普通动态规划(DP)求解LIS

1.DP思路

动态规划(DP)是一种通过将大问题分解为小问题来求解的方法。对于LIS,我们可以用DP逐步计算出每个位置的最优解,最终得到全局最优解。核心思想是:对于每个元素,考虑它能接在哪些之前的元素后面,形成更长的递增子序列

2.DP的状态定义与转移方程

状态定义
定义 dp[i] 表示 第 i 个元素 nums[i] 结尾最长递增子序列的长度
例如,dp[0] 表示以 nums[0] 结尾的LIS长度,dp[1] 表示以 nums[1] 结尾的LIS长度。

状态转移方程
对于位置 i,我们需要检查它之前的所有位置 j(0 ≤ j < i):
如果 nums[j] < nums[i],说明 nums[i] 可以接在 nums[j] 后面,形成一个更长的递增子序列。此时,dp[i] 可以更新为 dp[j] + 1。
为了确保 dp[i] 是最大的,我们需要从所有满足条件的 j 中挑选 dp[j] 最大的值,然后加 1

dp[i] = max(dp[j] + 1) 对于所有 j < i 且 nums[j] < nums[i]  这里遍历所有可能的j情况取最大的那一种就行

如果没有满足条件的 j(即 nums[i] 比之前所有元素都小),则 dp[i] = 1,因为它自身就是一个长度为 1 的子序列。
初始化
每个 dp[i] 初始值为 1,因为最短的递增子序列就是元素本身。
最终答案
遍历整个 dp 数组,找到最大的 dp[i],这就是整个序列的LIS长度

3.DP的时间与空间复杂度

时间复杂度O(n²)!!!
外层循环遍历每个位置 i(n 次),内层循环遍历 0 到 i-1(平均 n/2 次),总复杂度为 O(n²)。

空间复杂度:O(n)
只需一个长度为 n 的 dp 数组存储状态

4.DP代码实现

#include <iostream>
#include <vector>
#include <algorithm> using namespace std;int lengthOfLIS(vector<int>& nums) {int n = nums.size();if (n == 0) return 0; // 空序列返回 0vector<int> dp(n, 1); // 初始化 dp 数组,每个位置至少为 1int maxLen = 1;// 记录全局最大 LIS 长度for (int i = 0; i < n; i++) {以第i个元素为结尾 dp[i]for (int j = 0; j < i; j++) {//遍历结尾元素i前面的元素if (nums[j] < nums[i]) {dp[i] = max(dp[i], dp[j] + 1); // 更新 dp[i]}}maxLen = max(maxLen, dp[i]); // 更新全局最大值}return maxLen;
}int main() {vector<int> nums = {10, 9, 2, 5, 3, 7, 101, 18};cout << "最长递增子序列长度: " << lengthOfLIS(nums) << endl; // 输出 4return 0;
}

5.DP的图文示例

在这里插入图片描述
结果总结
最终 dp 数组:[1, 1, 1, 2, 2, 3, 4, 4]
LIS 长度:4
表格字段说明
索引 i:当前处理元素的下标。
nums[i]:序列中第 i 个元素的值。
dp[i]:以 nums[i] 结尾的最长递增子序列的长度。
计算过程:描述 dp[i] 是如何从前面的 dp[j](j < i)计算得到的。
可能的子序列示例:一个以 nums[i] 结尾的递增子序列,仅为示例,不一定是全局最优解

二、贪心 + 二分查找求解LIS

1.思路分析

普通动态规划(DP)求 LIS 的时间复杂度是 O(n²)因为它需要比较每个元素与之前所有元素的关系。而“贪心 + 二分查找”方法通过一种更高效的方式,将复杂度降到 O(n log n)。其核心在于:

1.目标:维护一个“最优”的递增子序列(不一定是最终的 LIS),确保每个长度的子序列末尾元素尽可能小。这样,后续元素就更容易接在这个子序列后面,从而最大化 LIS 的长度
2.工具:使用一个数组 d,其中 tails[i] 表示长度为 i+1 的递增子序列的末尾元素的最小值
3.操作规则:!!!!!!!!!!!!!!!!!!!!!!!!!!

如果当前元素大于 tails 的最后一个元素,直接将它追加到 tails 末尾,延长子序列
如果当前元素小于等于 tails 的最后一个元素,用二分查找找到 tails 中第一个大于等于当前元素的位置,并替换它,优化某个长度的子序列末尾

重要说明:d数组本身不一定是最终的 LIS,但它的长度一定等于 LIS 的长度
在这里插入图片描述
这是算法竞赛入门到进阶这门书的原话解释,请大家仔细理解

关键点!!!
虽然 d 的长度是正确的它的元素只是用来维护这个长度的工具不一定直接对应原始序列中的一个实际递增子序列
但长度一定是最长的递增子序列的长度!!!!!!!!!!!!!

2.贪心 + 二分的时间与空间复杂度

时间复杂度:O(n log n)
遍历序列 n 次,每次二分查找复杂度为 O(log n)。

空间复杂度:O(n)
用于存储d 数组

三. 模板题讲解

1.洛谷B3637 最长上升子序列

在这里插入图片描述
题目不用分析,因为题意说的很清除了,现在我给出dp和贪心+二分的两种写法

1.dp写法

#include <iostream>
#include <algorithm>
using namespace std;
int n, arr[5005];
int dp[5005] ; // 以第i个数结尾的序列长度为dp[i];
int maxlen = 1;
int main()
{cin >> n;for (int i = 1; i <= n; i++){cin >> arr[i];dp[i] = 1;//初始化长度都为1 因为就是自己}for (int i = 1; i <= n; i++){for (int j = 1; j < i; j++)//遍历i之前的元素{if (arr[j] < arr[i])dp[i] = max(dp[i], dp[j] + 1);}}int maxa = 0;for (int i = 1; i <= n; i++){maxa = max(maxa, dp[i]);//找最大值}cout << maxa;return 0;
}

这样也能过,因为数据很小,n的范围我圈出来了,大家看上面的图

2.贪心+二分写法

#include <iostream>
using namespace std;
typedef long long ll;
const ll M = 1e5 + 5;
ll n, a[M], d[M], len;void slove()
{cin>>n;for (int i = 0;i<n;i++){cin >> a[i];}d[0]=a[0];len = 0;//长度为i+1 因为从0开始for (int i = 1;i<n;i++)//这里从1开始 因为0位置我们初始化了{if(a[i]>d[len])//直接放入即可{len++;//这个别忘记d[len] = a[i];}else if(a[i]<d[len]){//查找第一个大于或等于a[i]的元素ll pos = lower_bound(d, d + len + 1, a[i]) - d;d[pos] = a[i];//其实没找到也没啥 因为没找到会返回数组last的位置 所以这里不判断也没事 长度又没更新}}cout << len + 1; // 别忘记加1 因为从0开始
}signed main()
{//关流 加速输入输出ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);slove();return 0;
}

2.洛谷P3902 递增

在这里插入图片描述
大家仔细看n最大可以到1e5,那么就不能再用dp的双重循环了
如果有网友不信邪,可以自己试试哦哈哈哈
那么这里我直接给一份贪心+二分代码

1.贪心+二分写法

#include <iostream>
using namespace std;
typedef long long ll;
const ll M = 1e5 + 5;
ll n, a[M], d[M], len;void slove()
{cin>>n;for (int i = 0;i<n;i++){cin >> a[i];}d[0]=a[0];len = 0;//长度为i+1 因为从0开始for (int i = 1;i<n;i++)//这里从1开始 因为0位置我们初始化了{if(a[i]>d[len])//直接放入即可{len++;//这个别忘记d[len] = a[i];}else if(a[i]<d[len]){//查找第一个大于或等于a[i]的元素ll pos = lower_bound(d, d + len + 1, a[i]) - d;d[pos] = a[i];//其实没找到也没啥 因为没找到会返回数组last的位置 所以这里不判断也没事 长度又没更新}}cout << n-(len + 1); // 别忘记加1 因为从0开始
}signed main()
{//关流 加速输入输出ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);slove();return 0;
}

四.练习题

1.洛谷P1091 [NOIP 2004 提高组] 合唱队形

在这里插入图片描述

1.思路分析

题目意思我们可以翻译为从数组中找一个点p,然后从前到这个点找一个递增子序列,从后到这个点找一个递增子序列,使得两个子序列和最大就行
在这里插入图片描述
全部代码我放在GitHub上了可以点击此处进入,记得挂梯子哦

2.洛谷P1020 [NOIP 1999 提高组] 导弹拦截

在这里插入图片描述

1.思路分析

第一个输出很常规,就是从后往前找一个最长递增子序列,因为题目说的是找递减的,因为后面的不能比前面的大,那我们反过来求就行
但第二个输出是一个关键点!!!!!!!
问题的本质
这个问题实际上是在问:如何用最少的严格递增子序列来覆盖整个序列。根据组合数学中的一个重要定理——Dilworth 定理(在偏序集上),我们可以得出以下结论

一个序列能被划分成的最少严格递增子序列的数量,等于该序列中最长的严格递减子序列!!!

换句话说,要解决这个问题,我们需要:

1.计算序列中最长的严格递减子序列的长度。
2.这个长度就是答案

那么我们一开始说了,这道题中我们从后往前求出来的就是递增子序列,所以显而易见,求递减子序列,我们只要从前往后就行

全部代码我放在GitHub上了可以点击此处进入,记得挂梯子哦

总结

大家可以发现 稍微难一点的都会卡n的范围,故意设置到1e5,所以这个LIS的贪心+二分的方法很有必要学习
还有就是练习题第2道的求最少多少个 递增! 子序列可以覆盖全部数组数据的这个定理请牢记!
数组的最长严格 递减 !子序列的长度即为数量

http://www.dtcms.com/wzjs/174165.html

相关文章:

  • 网站模板兼容手机端什么软件可以免费发广告
  • wordpress换icon搜索引擎优化seo网站
  • 找做模型方案去哪个网站国内免费域名注册
  • 手机动态网站制作seo搜索引擎优化方法
  • 2018做网站还赚钱吗百度关键词首页排名
  • 做网站用哪个软件最好php注册网站流程
  • 徐州教育平台网站建设网站收录优化
  • 企业网站建设规划书吴中seo网站优化软件
  • 慧聪网de网站建设策略seo 工具
  • 网站首页图片切换360站长
  • 做网站需要留什么条件重庆黄埔seo整站优化
  • b2b网站建设案例网络舆情管理
  • 英国有哪些做折扣的网站站长工具之家
  • 写作网站可以签约未成年吗搜狗seo培训
  • 济宁有做企业网站吗广告软文营销平台
  • 游戏网站制作模板设计模板网站
  • 做资格核查在哪个网站信息流推广渠道
  • 建设部监理网站官网安卓aso关键词优化
  • 做的网站侵犯美的商标赔偿多少钱搜索seo优化托管
  • 网页设计图片如何显示百度seo排名优化如何
  • 网站自助平台推广形式有哪几种
  • 地产商网站建设网站模板哪里好
  • 好看的登录页面自适应模板长沙优化科技有限公司
  • 织梦网站模块谷歌商店app下载
  • 哪个网站有成品的毕业论文站长之家域名解析
  • 深圳营销型网站公司电话百度推广怎么弄
  • 网站建设800元全包全网推广公司
  • 临河做网站seo中文意思
  • 潍坊做公司网站360关键词指数查询
  • 免费网站建设ydwzjs推广下载app拿佣金