携程笔试0907

4

题目

游游有一个只包含'0'和'1'的字符串,他想知道这个字符串有多少个好子串?

一个字符串如果是“好串”,那么该字符串的所有前缀,'0'的数量严格大于'1'的数量。

  • 输入描述

输入一个只包含'0'和'1'的字符串,长度不超过100000。

  • 输出描述

输出一个整数,代表答案。

  • 示例1

输入

100

输出

3

分析

熟练度不太行,想到一点思路没来得及写出来...

首先看数据范围,n <= 1e5,所以暴力遍历每个区间必然会超时。我们使用的算法的时间复杂度需要是 O(nlogn) 或者 O(n)。

由定义可以得到,如果一个子串是“好串”,那么依次从它的尾部删去一个字符,剩余的子串依然是“好串”。所以对于每个位置,如果以该位置为开头的最长“好串”长度为 length,那么以该位置为开头的“好串”就有 length 个。

如果把字符串的 '0' 对应到 1,'1' 对应到 -1,那么 [i, j] 为好串的条件就等价于 i 处为 '0' 且前缀和数组 pre 对所有 i<=k<=j 满足 pre[k] >= pre[i]。寻找以 i (下标从1开始)为开头的最长“好串”,就等价于寻找 i 右侧第一个使得 [i,j] 不是“好串”的最小的 j。这等价于寻找 i 右侧使得 pre[j] < pre[i] 的最小的 j,问题转化为典型的单调栈问题。

代码

s = input()
n = len(s)
pre = [0] * (n + 1)
str2num = {"0": 1, "1": -1}
for i in range(1, n + 1):
    pre[i] = pre[i - 1] + str2num[s[i - 1]]

stack = [(n + 1, int(1e9))] # (idx, pre[idx]) 初始化的时候加入最右侧的哨兵
cnt = 0
i = n
j = n # 单调栈未处理过的前缀和数组的最右侧的位置
while i > 0:
    # 对每个 i 找到 i 右侧第一个小于 pre[i] 的 pre[j] 和 j
    if s[i - 1] == "0":
        while j > i:
            while stack and stack[-1][1] >= pre[j]:
                stack.pop()
            stack.append((j, pre[j]))
            j -= 1
        if stack[0][1] >= pre[i]: # 右侧最小值
            cnt += n + 1 - i
        else:
            while stack[-1][1] >= pre[i]:
                stack.pop()
            cnt += stack[-1][0] - i
    i -= 1
print(cnt)

i 和 j 只会向左移动,前缀和数组的每项最多入栈一次、出栈一次,时间复杂度为 O(n)。

#携程笔试##笔试##秋招##携程#
全部评论
这个可以一次遍历解决,记录0,1结尾就行, 设个dp,dp[0] = 0 if nums[0] == 1 else 1, 然后遍历, dp[i] = dp[i-1] + 1 if nums[i] == 0 else dp[i-1] - 1 最后返回sum(dp)就OK了。 分析:记录每个位置结尾的好串个数
6 回复 分享
发布于 2023-09-08 14:51 广东
第三题我有个很短的写法,一次for循环出来了
点赞 回复 分享
发布于 2023-09-08 01:02 北京
推荐 九龙湖摸鱼大师 在 https://www.nowcoder.com/feed/main/detail/3afe8632d56341c19ee4e13f84adb68a?sourceSSR=search 9楼的评论,基于贪心做的,应该是时间空间都最高效的解法了,测试了一下常数是我的 1/5 到 1/6 左右
点赞 回复 分享
发布于 2023-09-08 00:54 北京
佬,有其他题目吗,想看看
点赞 回复 分享
发布于 2023-09-07 23:59 北京

相关推荐

03-29 15:34
门头沟学院 Java
北斗导航Compass低仿版:能不能先搞清楚优先级啊,怎么可能是项目问题,项目很重要吗?又没学历 又没实习大厂凭啥约面?那玩具项目 没应用在真实生产环境下的 就算做上天又有什么用?早点找个小公司实习 拿小公司实习去投大厂实习,这才是你现在该做的
投递美团等公司8个岗位 简历被挂麻了,求建议
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
昨天 11:43
春招失败、父母离婚,好像我的人生一团糟,一年来压力大到常常崩溃。不知道能跟谁聊,朋友其实对我非常好,但是她无意中表达出来的家庭幸福都会刺痛到我……和ai聊天,我的未来在更高处,不在楼下,忍不住爆哭😭
youngfa:害,妹妹,我是一个研究生(很上进很想找到好工作的那种),但去年因为生病回家休养错过了秋招(当时对我的冲击也是非常大的),这学期返校来了也是把论文盲审交了后才开始找工作,现在也是一个offer没有,但我就没有像你一样把这个阶段性的事情绑定到人生上,人生不仅很长,也很广阔,先停下来,放松一下哦。不要被外部环境灌输的思维操控了,好好爱自己!
点赞 评论 收藏
分享
评论
14
24
分享

创作者周榜

更多
牛客网
牛客企业服务