【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【贪心】2023C-有效子字符串【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录

  • 题目描述与示例
    • 题目
    • 输入
    • 输出描述
    • 示例一
      • 输入
      • 输出
    • 示例二
      • 输入
      • 输出
  • 解题思路
  • 代码
    • Python
    • Java
    • C++
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

题目描述与示例

题目

输入两个字符串SL,都只包含小写字母,len(S) <= 100len(L) <= 500000。判断S是否是L的有效子字符串。

  • 判定规则:S中的每个字符在L中都能找到(可以不连续),且SL中字符的前后顺序与S中顺序要保持一致。

例如:

S = "ace"L = "abcde"的一个子序列,且有效字符是ace,而"aec"不是有效子序列,且有效字符只有ae(因为相对位置不同)。

输入

输入两个字符串SL,都只包含小写字母,len(S) <= 100len(L) <= 500000,先输入S再输入L 每个字符串占一行。

输出描述

S`串**最后一个有效字符**在`L`中的位置,首位从`0`开始计算。无有效字符返回 `-1

示例一

输入

ace
abcde

输出

4

示例二

输入

fgh
abcde

输出

-1

解题思路

注意,本题和LC392. 判断子序列几乎完全一致。唯一的不同之处在于本题不仅要判断S能够由L构成,还要得到S最后一个有效字符L中的位置。这实际上进一步提醒我们应该用贪心思想来解决这个问题。

仅需一个简单地例子就可以看出为何要使用贪心思想:假设L = "abac"S = "abc"。当我们做字符匹配时,当然会选择L中的第一个"a"而不是第二个"a"来与S中的"a"进行匹配。因为只有选择了尽量靠前的"a",才能使得S更有可能由L中的字符按照顺序构成。

故我们只需设置两个同向双指针plps,分别用于LS从左到右的遍历。当

  • S[ps] == L[pl]时,说明当前L中字符能与S匹配,此时plps各自前进
  • S[ps] != L[pl]时,说明当前L中字符不能与S匹配,此时ps不应该移动,pl前进一位,去寻找L中下一个能和S[ps]匹配的字符。

上述过程应该在一个while循环中进行,退出循环的条件是pl到达L末尾nl或者ps到达S末尾ns。故上述算法的主体代码为

while(ps < ns and pl < nl):
    if S[ps] == L[pl]:
        ps += 1
        pl += 1
    else:
        pl += 1

退出循环时,如果

  • ps == ns,说明S中的每一个字符都能按顺序地在L中找到,输出pl-1的值即为S最后一个字符在L中出现的尽量靠前的位置。
  • ps != ns,说明无法成功匹配,输出-1
print(pl-1 if ps == ns else -1)

代码

Python

# 题目:2023C-有效子字符串
# 分值:100
# 作者:许老师-闭着眼睛学数理化
# 算法:贪心+同向双指针
# 代码看不懂的地方,请直接在群上提问

S = input()
L = input()

ns, nl, ps, pl = len(S), len(L), 0, 0
while(ps < ns and pl < nl):
    # 如果S[ps]等于L[pl],那么ps和pl都向前移动
    if S[ps] == L[pl]:
        ps += 1
        pl += 1
    # 如果S[ps]不等于L[pl],只有pl向前移动
    else:
        pl += 1

# 退出循环时,如果ps等于ns,说明S属于L的子序列
# 返回pl的值,即S最后一个字符在L中出现的位置
print(pl-1 if ps == ns else -1)

Java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String S = scanner.next();
        String L = scanner.next();

        int ns = S.length();
        int nl = L.length();
        int ps = 0;
        int pl = 0;

        while (ps < ns && pl < nl) {
            if (S.charAt(ps) == L.charAt(pl)) {
                ps++;
                pl++;
            } else {
                pl++;
            }
        }

        System.out.println((ps == ns) ? (pl - 1) : -1);
    }
}

C++

#include 
#include 

int main() {
    std::string S, L;
    std::cin >> S >> L;

    int ns = S.length();
    int nl = L.length();
    int ps = 0;
    int pl = 0;

    while (ps < ns && pl < nl) {
        if (S[ps] == L[pl]) {
            ps++;
            pl++;
        } else {
            pl++;
        }
    }

    std::cout << ((ps == ns) ? (pl - 1) : -1) << std::endl;

    return 0;
}

时空复杂度

时间复杂度:O(N+M)。同向双指针算法,每一个字符仅需遍历一次。

空间复杂度:O(1)。仅需要用到若干常数变量。

NS的长度,ML的长度。


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(最新华为OD真题,#,双指针,#,贪心,java,c++,华为od,leetcode,算法,python,双指针)