【经典算法】寻找最长01字串(转自待字闺中)

这两天在微信公众号“待字闺中”中看到一个经典的面试算法,寻找最长01字串,原题目是这么说的:

给定一个数组,数组中只包含0和1。请找到一个最长的子序列,其中0和1的数量是相同的。

例1:10101010 结果就是其本身。
例2:1101000 结果是110100

这个题目,看起来比较简单,一些同学可能认为题目的描述符合动态规划的特征,然后就开始用动态规划解,努力找状态转移方程。这些同学的感觉,是很正确的。但,找状态转移方程,我们要对原来的数组进行变换一下。

原来是0和1的串,我们将0都换为-1。这样题目目标就变成,找到一个最长的子串,子串数字和是0。设原数组为A, DP[i]表示从0开始到i的子数组和。DP遍历一遍数组即可。例1中的数组产生的DP为:

0 1 2 3 4 5 6 7
1 0 1 0 1 0 1 0

这个例子,最后一个值是0,并且长度是偶数位。直接满足了结果。

再看例子2:

0 1 2 3 4 5 6
1 2 1 2 1 0 -1

5的位置为0,最长子串从0开始到5,长度为6。

上面这两个例子,所求的子串都是从头开始,如果不是从头开始,会是什么样的呢?看这个例子:1101100

0 1 2 3 4 5 6
1 2 1 2 3 2 1

通过观察上面的表格,我们可以得到,DP[0]==DP[6]==DP[2],DP[1]==DP[3]. 根据DP的定义,如果DP[i]==DP[j],i 一种方法,我们用map保存DP的值到位置的映射,如下表:

DP值 位置 最大位置 最小位置 最大长度
1 0,2,6 6 0 6
2 1,3 3 1 2
3 4 4 4 0
最长子串长度       6

我们最终的算法,要综合考虑最常穿是否从头开始的。 上面的这个思路,时间复杂度是O(n),空间复杂度也是O(n).

还有其他的思路,例如DP保存的是[0,i]的1的个数,那么DP[j] - DP[i] * 2 == j - i则表明A[i+1]...A[j]是一个满足条件的串,找到j-i最大的,就是最终的结果,这个思路的时间复杂度为O(n^2),空间复杂度为O(n).

【分析完毕】

时间: 2024-08-02 07:02:39

【经典算法】寻找最长01字串(转自待字闺中)的相关文章

【算法】—妙:01字串

问题描述 对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能.它们的前几个是: 00000 00001 00010 00011 00100 请按从小到大的顺序输出这32种01串. 输入格式 本试题没有输入. 输出格式 输出32行,按从小到大的顺序每行一个长度为5的01串. 样例输出 00000000010001000011<以下部分省略> 该题是蓝桥杯<基础联系中得一道题>,最开始还在想要如何如何设置数组进行保存,但是经过片刻思考: 该题要求从低到高输出5位数得01

【编程题目】最长公共字串

56.最长公共字串(算法.字符串).题目:如果字符串一的所有字符按其在字符串中的顺序出现在另外一个字符串二中,则字符串一称之为字符串二的子串.注意,并不要求子串(字符串一)的字符必须连续出现在字符串二中.请编写一个函数,输入两个字符串,求它们的最长公共子串,并打印出最长公共子串.例如:输入两个字符串 BDCABA 和 ABCBDAB,字符串 BCBA 和 BDAB 都是是它们的最长公共子串,则输出它们的长度 4,并打印任意一个子串. 经典动态规划题. #include <stdio.h> #i

最长递归子序列、最长公共字串、最长公共子序列、编辑距离

[TOC]   ### 最长递归子序列 #### 题目 给定数组arr,返回arr中的最长递增子序列,如`arr=[2,1,5,3,6,4,8,9,7]`,返回的最长递增子序列为`[1,3,4,8,9]` #### 题解思路 先用DP来求解子序列递增的最大长度,如arr的长度序列为`dp=[1,1,2,2,3,3,4,5,4]`,然后对这个长度序列dp从右到左遍历,得到最长递增子序列. 1. 求解长度序列,令dp[i]表示在以arr[i]这个数结尾的情况下,arr[0...i]中的最大递增子序列

最长公共子序列(LCS)问题 Longest Common Subsequence 与最长公告字串 longest common substr

问题描述:字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X的子序列,存在X的一个严格递增下标序列<i0,i1,…,ik-1>,使得对所有的j=0,1,…,k-1,有xij=yj.例如,X=“ABCBDAB”,Y=“BCDB”是X的一个子序列. 考虑最长公共子序列问题如何分解成子问题,设A=“a0,a1,…,am-1”,B=“b0,b1,…,bm

蓝桥杯 基础练习 01字串 【暴力解决】

基础练习 01字串 时间限制:1.0s   内存限制:256.0MB 问题描述 对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能.它们的前几个是: 00000 00001 00010 00011 00100 请按从小到大的顺序输出这32种01串. 输入格式 本试题没有输入. 输出格式 输出32行,按从小到大的顺序每行一个长度为5的01串. 样例输出 00000 00001 00010 00011 <以下部分省略> #include<stdio.h> int mai

URAL 1517 Freedom of Choice(后缀数组,最长公共字串)

题目 输出最长公共字串 #define maxn 200010 int wa[maxn],wb[maxn],wv[maxn],ws[maxn]; int cmp(int *r,int a,int b,int l) {return r[a]==r[b]&&r[a+l]==r[b+l];}//yuan lai zhi qian ba zhe li de l cuo dang cheng 1 le ... void da(int *r,int *sa,int n,int m) { int i,j

搜索里的相似度计算-最长公共字串

相似度计算的任务是根据两段输入文本的相似度返回从0到1之间的相似度值:完全不相似,则返回0,:完全相同,返回1.衡量两端文字距离的常用方法有:海明距离(Hamming distance),编辑距离,欧氏距离,文档向量的夹角余弦距离,最长公共字串. 1. 余弦相似度 把两篇文档看作是词的向量,如果x,y为两篇文档的向量,则:Cos(x, y) = (x * y) / (||x|| * ||y||) 使用Hashmap可以很方便的把这个计算出来 2. 最长公共字串(Longest Common Su

lqb 基础练习 01字串 (itoa)

基础练习 01字串 时间限制:1.0s   内存限制:256.0MB 问题描述 对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能.它们的前几个是: 00000 00001 00010 00011 00100 请按从小到大的顺序输出这32种01串. 输入格式 本试题没有输入. 输出格式 输出32行,按从小到大的顺序每行一个长度为5的01串. 样例输出 00000 00001 00010 00011 <以下部分省略> 分析: 可以通过itoa(int n, char *, int

最长公共子序列与最长公共字串

显然最长公共子序列不一定需要连续的,只要字符的顺序严格递增即可.最长公共字串需要字符连续 子序列代码: package test; import java.util.*; /* * 本题是求最长公共子序列,子序列未必连续,只需要严格递增即可 * 如 abcdeeeeeeeee和atttbggcd 最长公共子序列为abcd 长度为4 * * */ public class Main4{ public static void main(String... args){ try(Scanner in