
18 一个01字符串,求出现0、1出现次数相等的最长子串长度
发布日期:2021-05-08 19:31:10
浏览次数:14
分类:精选文章
本文共 2767 字,大约阅读时间需要 9 分钟。
一个01字符串,求出现0、1出现次数相等的最长子串长度
题目描述:
已知一个长度为N的字符串,只由0和1组成, 求一个最长的子串,要求该子串出0和1出现的次数相等。
要求算法时间复杂度尽可能的低。
比如: 10000010111000001,所求为8,加粗的部分有4个0、4个1
最简单的想法就是遍历所有的子串,之后判断该子串是否满足条件N^2子串,每个子串扫一遍判断0、1是否出现的次数相等,复杂度为O(N^3)
方法一:
稍加思考就会发现, 如果一个长度为n的子串满足条件,加么这n个元素的和加起来一定=(n/2),且
子串长度为偶数,这样在循环的过程中,增量加就可以了,不需要每个子串从头计算,复杂度降为O(N^2).
该思想的程序为fun():
int fun(char num[],int n){ int i,j; int maxlen=0;//所求 int sum,currentlen;//当前子串和与当前子串长度 //挨个判断每个子串是否符合要求,若符合,则更新maxlen for(i=0;imaxlen) maxlen = currentlen; } } return maxlen;}
方法二:
和fun()的主体差不多,设了一个sum来判断每个子串中0,1个数是否相等,遇到0,sum--;遇到1,sum++。fun()和fun2()求子串的思路和方法要领会,它是以求以每个字符开头的所有子串这样的方式求的,外面再包个大循环就能求出所有子串。
int fun2(char num[],int n){ int i,j; int maxlen=0;//所求 int sum,currentlen;//当前子串和与当前子串长度 //挨个判断每个子串是否符合要求,若符合,则更新maxlen for(i=0;imaxlen) maxlen = currentlen; } } return maxlen;}
方法三:
一种巧妙的解法:定义一个数据temp[N], temp[i]表示从num[0...i]中 num_of_0 - num_of_1,0的个数与1的个数的差那么如果num[i+1] ~ num[j]是符合条件的子串,一定有 temp[i] == temp[j],因为中间的部分0、1个数相等,相减等于0。只需要扫一遍num[N]就能把temp[N]构造出来了。这样问题就转换成了求距离最远的一对数,使得temp[i] == temp[j],因为temp[i]的范围一定是[-N,N],-N到N的范围所对应的从num[0]开始的子串的结尾下标i都存起来,这样每扫到temp[i],查数就行了。
设两个辅助数组temp[]与assist[],代表的意义如下:
temp[i]表示num[0...i]中0的个数与1的个数差(即0的个数减去1的个数),则必有 -n<=temp[i]<=n
assist[]为辅助数组,里面存了0,1个数差所对应的num的最小下标,初值为-1表示该处还未存入内容。
assist[0]表示0,1个数差为-n的从num[0]开始的子串的结尾位置,即num[0...i]中的i,此时num[0...i]串中0,1个数差为-n,assist[2*n]表示0,1个数差为n的从num[0]开始的子串的结尾位置,即num[0...i]中的i,此时num[0...i]串中0,1个数差为n,assist[k]表示0,1个数差为 k-n 的从num[0]开始的子串的结尾位置。即assist[k+n] = i 表示0,1个数差为k的子串为num[0...i]
int fun1(char num[],int n){ int maxlen=0;//所求 int currentlen;//当前子串长度 int temp[n]; int assist[2*n+1]; //temp[]和assist[]的意义见上 int i; int count[2]={0,0};//分别代表当前0和1的个数,count[0]为0的个数,count[1]为1的个数 for(i=0;i<2*n+1;i++) assist[i] = -1; for(i=0;imaxlen) maxlen = currentlen; } } return maxlen;}int main(){ char num[]="10000010111000001"; int maxlen = fun(num,strlen(num)); printf("maxlen=%d\n",maxlen); return 0;}
最后一种解法
/** * * 数字串,全为0,1组合而成。求一个最长的连续子串,其中0和1的个数相等。 * 比如: 01100111 --> 011001 * 110000011 --> 1100 / 0011 * * 方法: * 定义一个数组a,a[0] = 0 * 然后遍历输入输入数字串,遇到0,减1,遇到1,加1。含义就是,到目前位置,净值出现了多少个0或者1. * 在数组a中选择两个相等的值,比如都是-3,第一个-3表示到该元素为止,多出现了3个0,第二个-3还是表示 * 到该元素为止,多出3个0,那么这两个元素之间的0和1的个数必定相互抵消。 * 于是,所求子串等同于,数组a中距离最远的两个相同值。可以两次循环,复杂度o(n*n) * * 为了O(n)的复杂度,利用hash表代替数组。原理一样。 * **/public class ZeroOnePairs { public static void find(int[] input){ HashMapmap = new HashMap (); map.put(0, 0); int begin = 0; int max = 0; int current = 0; for(int i=0; i max){ max = i + 1 - l; begin = l; } } } for(int j=begin; j
参考文献
、
发表评论
最新留言
不错!
[***.144.177.141]2025年03月24日 09时10分36秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
CODING 敏捷实战系列课第三讲:可视化业务分析
2021-05-09
使用 CODING DevOps 全自动部署 Hexo 到 K8S 集群
2021-05-09
工作动态尽在掌握 - 使用 CODING 度量团队效能
2021-05-09
CODING DevOps 代码质量实战系列最后一课,周四发车
2021-05-09
CODING DevOps 深度解析系列第二课报名倒计时!
2021-05-09
CODING DevOps 线下沙龙回顾二:SDK 测试最佳实践
2021-05-09
翻译:《实用的Python编程》03_01_Script
2021-05-09
数据结构第八节(图(下))
2021-05-09
基础篇:异步编程不会?我教你啊!CompletableFuture
2021-05-09
基于Mustache实现sql拼接
2021-05-09
气球游戏腾讯面试题滑动窗口解法
2021-05-09
POJ 2260 Error Correction 模拟 贪心 简单题
2021-05-09
POJ - 1328 Radar Installation 贪心
2021-05-09
CSUOJ Water Drinking
2021-05-09
自定义博客园博客的背景图片
2021-05-09
Spring MVC+javamail实现邮件发送
2021-05-09
Asp.NET Core 限流控制-AspNetCoreRateLimit
2021-05-09
gRPC在 ASP.NET Core 中应用学习(一)
2021-05-09
@SuppressWarnings 用法
2021-05-09
看完你就明白的锁系列之锁的状态
2021-05-09