#C17. 华为OD机试统一考试D卷C卷 - 求满足条件的最长子串的长度

华为OD机试统一考试D卷C卷 - 求满足条件的最长子串的长度

题目链接

华为OD机试统一考试D卷C卷 - 求满足条件的最长子串的长度(C++ Java JavaScript Python)

https://blog.csdn.net/banxia_frontend/article/details/134564473

题目描述

给定一个字符串,只包含字母和数字,按要求找出字符串中的最长(连续)子串的长度,字符串本身是其最长的子串,子串要求: 1、 只包含1个字母(a~z, A~Z),其余必须是数字; 2、 字母可以在子串中的任意位置; 如果找不到满足要求的子串,如全是字母或全是数字,则返回-1。

输入描述

字符串(只包含字母和数字)

输出描述

子串的长度

用例

输入abC124ACb
输出4
说明满足条件的最长子串是C124或者124A,长度都是4
输入a5
输出2
说明字符串自身就是满足条件的子串,长度为2
输入aBB9
输出2
说明满足条件的子串为B9,长度为2
输入abcdef
输出-1
说明没有满足要求的子串,返回-1

C++

#include <iostream>
#include <deque>
#include <string>

using namespace std;

int main() {
    // 读取输入的字符串
    string str;
    cin >> str;

    // 初始化最长子串长度为-1
    int maxLen = -1;
    // 初始化一个标志,表示是否找到了包含字母的子串
    bool hasLetter = false;

    // 初始化双指针l和r,分别表示子串的左右边界
    int l = 0, r = 0;
    // 创建一个双端队列用于存储字母的索引
    deque<int> letterIdx;

    // 遍历字符串
    while (r < str.length()) {
        // 获取当前字符
        char c = str[r];

        // 如果当前字符是字母
        if (isalpha(c)) {
            // 设置标志为true,表示找到了包含字母的子串
            hasLetter = true;
            // 将字母的索引添加到队列的尾部
            letterIdx.push_back(r);

            // 如果队列中有多于1个字母的索引
            if (letterIdx.size() > 1) {
                // 移除队列头部的字母索引,并将左指针l移动到该索引的下一个位置
                l = letterIdx.front() + 1;
                letterIdx.pop_front();
            }

            // 如果右指针r等于左指针l,跳过当前循环
            if (r == l) {
                r++;
                continue;
            }
        }

        // 更新最长子串长度
        maxLen = max(maxLen, r - l + 1);
        // 移动右指针
        r++;
    }

    // 如果没有找到包含字母的子串,输出-1
    if (!hasLetter) {
        cout << -1 << endl;
    } else {
        // 否则输出最长子串长度
        cout << maxLen << endl;
    }

    return 0;
}

java


import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        // 创建Scanner对象用于读取输入
        Scanner sc = new Scanner(System.in);
        // 读取输入的字符串
        String str = sc.next();
        // 初始化最长子串长度为-1
        int maxLen = -1;
        // 初始化一个标志,表示是否找到了包含字母的子串
        boolean hasLetter = false;

        // 初始化双指针l和r,分别表示子串的左右边界
        int l = 0, r = 0;
        // 创建一个双端队列用于存储字母的索引
        Deque<Integer> letterIdx = new ArrayDeque<>();

        // 遍历字符串
        while (r < str.length()) {
            // 获取当前字符
            char c = str.charAt(r);

            // 如果当前字符是字母
            if (Character.isLetter(c)) {
                // 设置标志为true,表示找到了包含字母的子串
                hasLetter = true;
                // 将字母的索引添加到队列的尾部
                letterIdx.addLast(r);

                // 如果队列中有多于1个字母的索引
                if (letterIdx.size() > 1) {
                    // 移除队列头部的字母索引,并将左指针l移动到该索引的下一个位置
                    l = letterIdx.removeFirst() + 1;
                }

                // 如果右指针r等于左指针l,跳过当前循环
                if (r == l) {
                    r++;
                    continue;
                }
            }

            // 更新最长子串长度
            maxLen = Math.max(maxLen, r - l + 1);
            // 移动右指针
            r++;
        }

        // 如果没有找到包含字母的子串,输出-1
        if (!hasLetter) {
            System.out.println(-1);
        } else {
            // 否则输出最长子串长度
            System.out.println(maxLen);
        }
    }
}

javaScript

const readline = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});

// 读取输入的字符串
readline.on('line', (str) => {
  // 初始化最长子串长度为-1
  let maxLen = -1;
  // 初始化一个标志,表示是否找到了包含字母的子串
  let hasLetter = false;

  // 初始化双指针l和r,分别表示子串的左右边界
  let l = 0, r = 0;
  // 创建一个双端队列用于存储字母的索引
  let letterIdx = [];

  // 遍历字符串
  while (r < str.length) {
    // 获取当前字符
    let c = str.charAt(r);

    // 如果当前字符是字母
    if (c.match(/[a-zA-Z]/)) {
      // 设置标志为true,表示找到了包含字母的子串
      hasLetter = true;
      // 将字母的索引添加到队列的尾部
      letterIdx.push(r);

      // 如果队列中有多于1个字母的索引
      if (letterIdx.length > 1) {
        // 移除队列头部的字母索引,并将左指针l移动到该索引的下一个位置
        l = letterIdx.shift() + 1;
      }

      // 如果右指针r等于左指针l,跳过当前循环
      if (r === l) {
        r++;
        continue;
      }
    }

    // 更新最长子串长度
    maxLen = Math.max(maxLen, r - l + 1);
    // 移动右指针
    r++;
  }

  // 如果没有找到包含字母的子串,输出-1
  if (!hasLetter) {
    console.log(-1);
  } else {
    // 否则输出最长子串长度
    console.log(maxLen);
  }

  readline.close();
});

python

from collections import deque

# 读取输入的字符串
str = input()

# 初始化最长子串长度为-1
maxLen = -1
# 初始化一个标志,表示是否找到了包含字母的子串
hasLetter = False

# 初始化双指针l和r,分别表示子串的左右边界
l, r = 0, 0
# 创建一个双端队列用于存储字母的索引
letterIdx = deque()

# 遍历字符串
while r < len(str):
    # 获取当前字符
    c = str[r]

    # 如果当前字符是字母
    if c.isalpha():
        # 设置标志为true,表示找到了包含字母的子串
        hasLetter = True
        # 将字母的索引添加到队列的尾部
        letterIdx.append(r)

        # 如果队列中有多于1个字母的索引
        if len(letterIdx) > 1:
            # 移除队列头部的字母索引,并将左指针l移动到该索引的下一个位置
            l = letterIdx.popleft() + 1

        # 如果右指针r等于左指针l,跳过当前循环
        if r == l:
            r += 1
            continue

    # 更新最长子串长度
    maxLen = max(maxLen, r - l + 1)
    # 移动右指针
    r += 1

# 如果没有找到包含字母的子串,输出-1
if not hasLetter:
    print(-1)
else:
    # 否则输出最长子串长度
    print(maxLen)

C语言

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>

#define MAX_LEN 1000

// 创建一个双端队列用于存储字母的索引
int letterIdx[MAX_LEN];
int front = 0, rear = -1;

// 入队操作
void push(int idx) {
    rear++;
    letterIdx[rear] = idx;
}

// 出队操作
void pop() {
    front++;
}

// 获取队首元素
int getFront() {
    return letterIdx[front];
}

// 判断队列是否为空
bool isEmpty() {
    return rear < front;
}

int main() {
    // 读取输入的字符串
    char str[MAX_LEN];
    scanf("%s", str);

    // 初始化最长子串长度为-1
    int maxLen = -1;
    // 初始化一个标志,表示是否找到了包含字母的子串
    bool hasLetter = false;

    // 初始化双指针l和r,分别表示子串的左右边界
    int l = 0, r = 0;

    // 遍历字符串
    while (r < strlen(str)) {
        // 获取当前字符
        char c = str[r];

        // 如果当前字符是字母
        if (isalpha(c)) {
            // 设置标志为true,表示找到了包含字母的子串
            hasLetter = true;
            // 将字母的索引添加到队列的尾部
            push(r);

            // 如果队列中有多于1个字母的索引
            if (rear - front + 1 > 1) {
                // 移除队列头部的字母索引,并将左指针l移动到该索引的下一个位置
                l = getFront() + 1;
                pop();
            }

            // 如果右指针r等于左指针l,跳过当前循环
            if (r == l) {
                r++;
                continue;
            }
        }

        // 更新最长子串长度
        maxLen = r - l + 1 > maxLen ? r - l + 1 : maxLen;
        // 移动右指针
        r++;
    }

    // 如果没有找到包含字母的子串,输出-1
    if (!hasLetter) {
        printf("-1\n");
    } else {
        // 否则输出最长子串长度
        printf("%d\n", maxLen);
    }

    return 0;
}

完整用例

用例1

abC124ACb

用例2

a5

用例3

aBB9

用例4

abcdef

用例5

123456

用例6

aBcD1234567890EFG

用例7

aBcD1234567890EFGHijklmnopqrstuvwxyZ

用例8

aBcD1234aBcD1234aBcD1234

用例9

aBcD1234aBcD1234aBcD12345

用例10

aBcD1234aBcD1234aBcD1234a

@[TOC]

fengmian