出题:求数组中最长递增子序列的长度(递增子序列的元素可以不相连);

分析:

  • 解法1:应用DP之前需要确定当前问题是否具有无后效性,也就是每个状态都是对之前状态的一个总结,之后的状态仅会受到前一个状态的影响;对于递增子序列 而言,可以首先确定前面k个元素的最长子序列,然后计算增加一个元素之后的最长子序列。由于每个位置i都会与0-i的每个位置之前的LIS进行比较,并选 择保持递增的一个序列,所以总能找到LIS,但是时间复杂度为O(N^2),空间复杂度为O(N);
  • 此解法的性能的瓶颈在于对于位置为i+1的元素,都会遍历0到i内的每一个元素,比较元素本身,以及其位置上的record值;但问题的核心是找到一个最长的LIS,并且其序列中最后一个元素的值比array[i+1]小就可以;

解题:

 int version1(int *array, int length) {
/**
* record记录每个元素位置之前的LIS数
* */
int *record=new int[length];
for(int i=;i<length;i++) {
/**
* 将当前元素的LIS初始化为1
* */
record[i]=;
for(int j=;j<i;j++) {
/**
* 遍历元素i之前的所有元素j,判断j与i是否组成递增序列
* 如果是,则比较对应的record[j]是否比record[i]大1
* 如果是,则更新record[i]的值为record[j]+1
* 这样的策略则总能保证,record[i]的值是0到i区间最大
* 的LIS
* */
if(array[i]>array[j] && record[j]+>record[i]) {
record[i]=record[j]+;
}
}
} /**
* 从record中找出最大的LIS
* */
int max=record[];
for(int i=;i<length;i++) {
if(max<record[i])
max=record[i];
} return max;
} int main() {
int array[]={,-,,-,,-,,-,-};
printf("%d\n",version1(array, ));
return ;
}

出题:给定两个字符串S1和S2,要求判定S2是否可以通过S1做循环移位(rotate)得到的新字符串包含。(S1=AABCD和S2=CDAA,就是包含;S1=ABCD和S2=ACBD,不包含);

分析:

  • S2是移位之后的字符串,则S2的第一个字符对应到S1中的字符位置之前的字符肯定已经被rotate到后面;可以首先从S1中查找S2,如果某个字符不 相同,则跳到下一个可能的查找位置;如果S1到达末尾,则rotate前面的字符,继续对比;如果S2到达末尾,则说明包含;如果rotate之后对比的 字符不同,则不包含。此方法时间复杂度为O(MN);
  • 另外一个解法为将S1转变为SS1=AABCDAABCD,这样子在SS1上寻找S2,时间复杂度仍旧为O(MN),其实与上述方法策略相同;

解题:

 /**
* 翻转字符串,注意length为字符串长度,
* 而不是字符索引
* */
void Reverse(char *s, int length) {
char temp;
for(int i=;i<length/;i++) {
temp=s[i];
s[i]=s[length-i-];
s[length-i-]=temp;
}
}
/**
* 下面的方法实现以s2为分界的旋转,比如
* 字符串abcdef,s1指向a,s2指向d
* 则经过方法处理之后为defabc
* */
void HalfReverse(char *s1, char *s2) {
char *t=s1;
char length=, halflength=;
while(*t!='\0') {
if(*t==*s2)
halflength=length;
length++;
t++;
}
Reverse(s1,halflength);
Reverse(s2,length-halflength);
Reverse(s1,length);
};
/**
* 将s1作为循环主体,每一个字符作为比较的开始字符;
* s2平行在s1上移动比较
* s1仅可以进行一次旋转
* */
bool RotateContain(char *s1, char *s2, bool isRotate) {
char *s1t=s1, *s2t=s2; while(*s1t) {
char *s1tt=s1t;
char *s2tt=s2t; while(*s1tt!='\0' && *s2tt!='\0') {
if(*s1tt!=*s2tt)
break;
s1tt++;s2tt++;
}
/**
* 当s2到达末尾,表示成功匹配,返回true
* */
if(*s2tt=='\0')
return true;
/**
* 当s1到达末尾,有两种情况
* 如果isRotate为false,则可以进行一次旋转
* 如果isRotate为true,说明已经进行了一次旋转
* */
if(*s1tt=='\0') {
if(isRotate)
return false;
else {
isRotate=true;
HalfReverse(s1, s1t);
return RotateContain(s1,s2,isRotate);
}
}
s1t++;
}
return false;
} int main() { char s1[]="abcdefg";
char s2[]="defgabc";
bool isRotate=false;
if(RotateContain(s1,s2,isRotate))
printf("true");
else
printf("false");
return ;
}

笔试算法题(35):最长递增子序列 & 判定一个字符串是否可由另一个字符串旋转得到的更多相关文章

  1. Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流)

    Libre 6005 「网络流 24 题」最长递增子序列 / Luogu 2766 最长递增子序列问题(网络流,最大流) Description 问题描述: 给定正整数序列x1,...,xn . (1 ...

  2. 【刷题】LOJ 6005 「网络流 24 题」最长递增子序列

    题目描述 给定正整数序列 \(x_1 \sim x_n\) ,以下递增子序列均为非严格递增. 计算其最长递增子序列的长度 \(s\) . 计算从给定的序列中最多可取出多少个长度为 \(s\) 的递增子 ...

  3. 算法之动态规划(最长递增子序列——LIS)

    最长递增子序列是动态规划中最经典的问题之一,我们从讨论这个问题开始,循序渐进的了解动态规划的相关知识要点. 在一个已知的序列 {a1, a 2,...an}中,取出若干数组成新的序列{ai1, ai ...

  4. 【PowerOJ1741&网络流24题】最长递增子序列问题(最大流)

    题意: 思路: [问题分析] 第一问时LIS,动态规划求解,第二问和第三问用网络最大流解决. [建模方法] 首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K. ...

  5. [cogs731] [网络流24题#6] 最长递增子序列 [网络流,最大流]

    [转hzwer]第一问是LIS,动态规划求解,第二问和第三问用网络最大流解决.首先动态规划求出F[i],表示以第i位为开头的最长上升序列的长度,求出最长上升序列长度K.1.把序列每位i拆成两个点< ...

  6. 最长公共子序列(LCS)和最长递增子序列(LIS)的求解

    一.最长公共子序列 经典的动态规划问题,大概的陈述如下: 给定两个序列a1,a2,a3,a4,a5,a6......和b1,b2,b3,b4,b5,b6.......,要求这样的序列使得c同时是这两个 ...

  7. C++ 求最长递增子序列(动态规划)

    i 0 1 2 3 4 5 6 7 8 a[i] 1 4 7 2 5 8 3 6 9 lis[i] 1 2 3 2 3 4 3 4 5 时间复杂度为n^2的算法: //求最长递增子序列 //2019/ ...

  8. Cogs 731. [网络流24题] 最长递增子序列(最大流)

    [网络流24题] 最长递增子序列 ★★★☆ 输入文件:alis.in 输出文件:alis.out 简单对比 时间限制:1 s 内存限制:128 MB «问题描述: 给定正整数序列x1,-, xn. ( ...

  9. (转载)最长递增子序列 O(NlogN)算法

    原博文:传送门 最长递增子序列(Longest Increasing Subsequence) 下面我们简记为 LIS. 定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则 ...

随机推荐

  1. 将Mozilla ThunderBird最小化到系统托盘(转载)

    转自:http://be-evil.org/mozilla-thunderbird-minize-to-tray.html Mozilla ThunderBird是一款非常不错的邮件客户端,但是其在默 ...

  2. bzoj 4481: [Jsoi2015]非诚勿扰【期望+树状数组】

    首先很容易计算对于一个如意郎君列表里有x个男性的女性,编号排第i位的男性被选的概率是 \[ p*(1-p)^{i-1}+p*(1-p)^{i-1+n}+p*(1-p)^{i-1+n}+- \] \[ ...

  3. SpringBoot使用MongoDB

    一.什么是MongoDB MongoDB是一个基于分布式文件存储的数据库,由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的 ...

  4. 执行linux脚本出现问题

    1. 权限不够: 使用 chmod +x XXX.sh 提升权限 2. 出现:/bin/bash^M: bad interpreter: No such file or directory 原因:文件 ...

  5. this关键字的构造方法的使用

    package com.wh.Object3; public class this_Demo { private String name; private double price; private ...

  6. 策略模式--Java篇

    策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户. 下面将以商场打折为例子,说明策略模式.商场收银如何促销,用打折还是 ...

  7. [BZOJ2809][Apio2012]dispatching 贪心+可并堆

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2809 我们考虑以每一个节点作为管理者所得的最优答案,一定是优先选择所要薪水少的忍者.那么首 ...

  8. 常用linux命令大全 转载自:https://www.cnblogs.com/laov/p/3541414.html(大牛笔记)

    Linux简介及Ubuntu安装 Linux,免费开源,多用户多任务系统.基于Linux有多个版本的衍生.RedHat.Ubuntu.Debian 安装VMware或VirtualBox虚拟机.具体安 ...

  9. vue--组件中的自定义事件

    父组件通过props向子组件传递数据,子组件通过自定义事件向父组件传递信息. 在子组件中通过$emit触发事件,父组件在直接使用子组件的地方使用v-on(即@)来监听子组件触发的事件. 举例:(不知道 ...

  10. 在Windows7下编译调试C#程序

    要在 命令行下编译C#代码,要配置一下 1.在环境变量下新建一个变量 参数名: csc 参数值:C:\Windows\Microsoft.NET\Framework\v4.0.30319 2.在系统变 ...