题目来自编程之美

题目

思路(1) 动态规划(复杂度为n^2)

方程:

F[i]:表示以nArr[i]为结尾的最长递增子序列的最大长度。
F[i] = Max(F[j]) + 1 && a[i] > a[j] && i > j;

方程的直观含义:检查nArr[i]能接在哪一个数的后面。

如果要求LIS序列,需要令开辟一个数组。

复杂度:O(n^2)

代码:只求LIS的长度

#include <iostream>
#include <assert.h>
using namespace std;/*
F[i]:表示以nArr[i]为结尾的最长递增子序列的长度
F[i] = Max(F[j]) + 1 && a[i] > a[j] && i > j;
F[i] = 1
*/
int LIS(int nArr[],int nLen)
{int nMaxLen = 1;int* F = new int[nLen];//递推for (int i = 1;i < nLen;i++){F[i] = 1;for (int j = i - 1;j >= 0;j--){if (nArr[i] > nArr[j]){F[i] = max(F[i],F[j] + 1);}}nMaxLen = max(nMaxLen,F[i]);}//输出return nMaxLen;
}int main()
{int nArr[8] = {1,-1,2,-3,4,-5,6,-7};cout<<LIS(nArr,8)<<endl;system("pause");return 1;
}

代码:输出一个LIS序列

#include <iostream>
#include <assert.h>
using namespace std;void Print(int* nArr,int* Pre,int nCurPos)
{if (nCurPos == -1){return;}Print(nArr,Pre,Pre[nCurPos]);cout<<nArr[nCurPos]<<" ";
}/*
F[i]:表示以nArr[i]为结尾的最长递增子序列的长度
F[i] = Max(F[j]) + 1 && a[i] > a[j] && i > j;
F[i] = 1
*/
int LIS(int nArr[],int nLen)
{int nMaxLen = 1;int* F = new int[nLen];int* Pre = new int[nLen];int nMaxPos = -1;//递推for (int i = 1;i < nLen;i++){F[i] = 1;Pre[i] = -1;for (int j = i - 1;j >= 0;j--){if (nArr[i] > nArr[j]){if (F[i] < F[j] + 1){F[i] = F[j] + 1;Pre[i] = j;}}}if (nMaxLen < F[i]){nMaxLen = F[i];nMaxPos = i;}}//输出Print(nArr,Pre,nMaxPos);cout<<endl;return nMaxLen;
}int main()
{int nArr[8] = {1,-1,2,-3,4,-5,6,-7};cout<<LIS(nArr,8)<<endl;system("pause");return 1;
}

思路(2)O(nlogn)的算法

思路:数组nArrIncr中的数据都是不重复的。

代码:

int BinSearch(int nArrIncr[],int nNum,int nStart,int nEnd)
{int nMid = -1;while(nStart <= nEnd){nMid = (nStart + nEnd) >> 1;if (nArrIncr[nMid] == nNum){return nMid;//返回nNum的位置}else if (nArrIncr[nMid] > nNum){nEnd = nMid - 1;}else{nStart = nMid + 1;}}return nStart; //返回第一个大于nNum的位置
}int LIS(int nArr[],int nLen)
{assert(nLen > 0);int nEnd = 0;int* nArrIncr = new int[nLen];nArrIncr[0] = nArr[0];int nPos = -1;for (int i = 1;i < nLen;i++){if (nArr[i] > nArrIncr[nEnd]){nArrIncr[++nEnd] = nArr[i];}else{nPos = BinSearch(nArrIncr,nArr[i],0,nEnd);//寻找第一个大于等于nArr[i]的数nArrIncr[nPos] = nArr[i];}}return nEnd + 1;
}

利用STL,给出一个更简洁的代码:

int LIS(int nArr[],int nLen)
{assert(nLen > 0);int nEnd = 0;int* nArrIncr = new int[nLen];nArrIncr[0] = nArr[0];int nPos = -1;for (int i = 1;i < nLen;i++){if (nArr[i] > nArrIncr[nEnd]){nArrIncr[++nEnd] = nArr[i];}else{//寻找第一个大于等于nArr[i]的数*lower_bound(nArrIncr,nArrIncr + nEnd + 1,nArr[i]) = nArr[i];}}return nEnd + 1;
}

注:

lower_bound作用:在区间[first,last)进行二分查找,返回第一个大于或等于val的元素位置(迭代器)。

(1)如果所有元素都小于val,则返回last的位置,且last的位置是越界的

(2)头文件:#include <algorithm>

输出一个LIS,复杂度为O(n)

代码

#include <iostream>
#include <assert.h>
#include <algorithm>
using namespace std;void Print(int nArr[],int nCurLen,int nCurPos,int nArrPos[])
{if (nCurLen == 0){return;}if (nCurLen == nArrPos[nCurPos]){Print(nArr,nCurLen - 1,nCurPos - 1,nArrPos);cout<<nArr[nCurPos]<<" ";}else{Print(nArr,nCurLen,nCurPos - 1,nArrPos);}
}void LIS(int nArr[],int nLen)
{assert(nLen > 0);int nEnd = 0;int* nArrIncr = new int[nLen];int* nArrPos = new int[nLen];nArrIncr[0] = nArr[0];nArrPos[0] = 1; //每一个元素所在LIS的位置int nLastNumPos = 0;//LIS最后一个元素的下标for (int i = 1;i < nLen;i++){if (nArr[i] > nArrIncr[nEnd]){nArrIncr[++nEnd] = nArr[i];nArrPos[i] = nEnd + 1;//寻找LISnLastNumPos = i;//记录LIS最后一个元素的位置}else{//寻找第一个大于等于nArr[i]的数int nPos = lower_bound(nArrIncr,nArrIncr + nEnd + 1,nArr[i]) - nArrIncr;nArrIncr[nPos] = nArr[i];nArrPos[i] = nPos + 1;//记录每一个数是在LIS中第几个数}}//输出信息cout<<"长度: "<<nEnd + 1<<endl;cout<<"LIS: ";Print(nArr,nEnd + 1,nLastNumPos,nArrPos);cout<<endl;
}int main()
{//int nArr[8] = {1,-1,2,-3,4,-5,6,-7};//LIS(nArr,8);int nArr[1] = {-7};LIS(nArr,1);//int nArr[8] = {-7,10,9,2,3,8,8,1};//LIS(nArr,8);system("pause");return 1;
}

每日一题(79) - 求数组中最长递增子序列相关推荐

  1. 求数组中最长递增子序列的长度

    题目:写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度. 例:在序列[1, -1, 2, -3, 4, -5, 6, -7]中,其最长递增子序列的长度为4([1, 2, ...

  2. 程序员面试100题之十二:求数组中最长递增子序列

    写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度. 例如:在序列1,-1,2,-3,4,-5,6,-7中,其最长递增子序列为1,2,4,6. 分析与解法 根据题目要求, ...

  3. 求数组中最长递增子序列

    写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度. 例如: arr[] = {1, -1, 2, -3, 4, -5, 6, -7},其最长递增子序列的长度为4 如(1 ...

  4. 编程之美-求数组中最长递增子序列(LIS)方法整理

    [试题描述] 方法一:时间复杂度O(n^2) 方法二:时间复杂度O(n^2) 方法三: 修改方法二中的穷举搜索部分为如下: 如果把上述查询部分利用二分搜索进行加速,可以得到时间复杂度为O(nlogn) ...

  5. Java输出数组中最长递增子序列的代码

    下面内容是关于Java输出数组中最长递增子序列的内容,希望对大伙有较大用途. package com.wzs;import java.util.ArrayList; import java.util. ...

  6. c语言找出递增子数组的长度,编程之美2.16 数组中最长递增子序列的长度

    改进的方法看的头大了却还是不清楚,哎...搞算法的苦啊,纠结啊. 编程之美这本书里面就有关于这道题的一些解法,求一个一位数组中的最长序列的长度.例如,在序列1,3,2中,最长递增序列是1,3. 这道题 ...

  7. java数组排列组合_java算法题--递归求数组中数字排列组合问题

    java算法题–递归求数组中数字排列组合问题 题目:有一个数组{1,2,3},输出数组中数字的所有可能组合: 比如:123.132.213- 解题思路 通过递归不停的交换数组中的两个数(当然,肯定是有 ...

  8. 求数组中最长连续递增子序列

    求子数组的最大和 题目描述: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. 求所有子数组的和的最大值.要求时间复杂度为O(n). 例如输入 ...

  9. java二维数组数字数显次数_【每日一题】118.数组中数字出现的次数

    关注我们获取更多计算机考研信息 ? 今日习题 在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次.请找出那个只出现一次的数字. 示例 1: 输入:nums = [3,4,3,3] ...

最新文章

  1. AMI:加密的机器映像。卷
  2. java序列化与反序列化(转)
  3. [Hive_add_11] Hive 使用 UDTF 实现日志降维
  4. Dalvik/ART(ANDROID)中的多线程机制(1)
  5. 日本的酒店主题能有多丰富?
  6. 【推荐系统算法学习笔记1】基本架构、专有名词、构建流程
  7. 解决 ssh 登录到ubuntu server 慢的问题
  8. windows之解决VMware虚拟机经常性卡死
  9. lisp线段两端同时缩短的命令_老杨讲禅——线段与特征序列(1)
  10. MSN网页上点击连接
  11. 华为盒子EC6108V9/V9U/V92/V97-HI3798MV100(免拆机-通刷固件)卡刷固件及教程
  12. 计算机辅助设计和辅助制造简称,计算机辅助设计与制造
  13. 苹果AppId登录注册
  14. python检查https过期_Python实现HTTPS网站证书过期监控及更新
  15. MAXON宣布任命高级领导人员
  16. win10蓝牙链接上的标准串行com口无法删除
  17. LS1043A 查看 MAC、BMI、QMI寄存器, 查看网口发包丢包情况
  18. 苹果、安卓ASO优化,aso安卓苹果(二)
  19. 区块链应用开发入门(转)
  20. 模糊数学——模糊模式识别

热门文章

  1. 《盗梦空间》全解析_daomengkongjian_腾讯middot;大楚网
  2. Angular 服务的创建及使用
  3. 某招聘网站的数据分析师岗位分析
  4. 数据规范化(归一化)、及Z-score标准化
  5. 证明电压电流相位差的余弦值和功率因数相等
  6. HWC blending mode
  7. 准确率、召回率、F1值的思考
  8. ubuntu 20.04 下安装easyconnect记录
  9. maven 仓库下载地址
  10. 华为云连接CC,为企业出海保驾护航