题目链接

REAL736 订单分类

题目描述

小美需要根据订单的ID来判断它属于哪一类。ID由字母、数字和特殊字符组成。分类规则如下:

  • 如果ID以字母开头,并且后面只包含数字,则属于“electronics”。
  • 如果ID以数字开头,并且后面只包含字母,则属于“clothing”。
  • 如果ID以字母开头,并且后面只包含字母和数字,则属于“accessories”。
  • 如果ID以数字开头,并且后面只包含特殊字符(非字母和数字),则属于“invalid”。
  • 其他情况的ID都属于“miscellaneous”。

思路分析

本题要求我们根据一系列规则对给定的订单ID字符串进行分类。这是一个典型的字符串处理和多条件判断的模拟题。关键在于仔细分析规则的优先级和边界条件,并编写出清晰、无误的逻辑判断链。

一个重要的细节是规则的优先级。例如,规则“electronics”(字母开头,后跟纯数字)是规则“accessories”(字母开头,后跟字母和数字)的一个特例。因此,在检查以字母开头的ID时,我们必须先检查是否满足更具体的 electronics 规则,再检查 accessories 规则

我们可以将逻辑分解如下:

  1. 读取ID:对于每个ID字符串,首先判断其是否为空。如果为空,或者长度为1(不满足大部分规则),可以归为 miscellaneous

  2. 按首字符分类

    • 如果首字符是字母 (isalpha):
      1. 检查ID的剩余部分 (id.substring(1)) 是否全为数字。为满足此条件,剩余部分必须非空,且不包含任何字母或特殊字符。如果满足,则分类为 electronics
      2. 如果不满足上一条,则检查剩余部分是否只包含字母和数字 (isalnum)。如果ID剩余部分没有任何特殊字符,则满足此条件。分类为 accessories
      3. 如果以上都不满足(即剩余部分包含特殊字符),则分类为 miscellaneous
    • 如果首字符是数字 (isdigit):
      1. 检查ID的剩余部分是否全为字母。为满足此条件,剩余部分必须非空,且不包含任何数字或特殊字符。如果满足,则分类为 clothing
      2. 如果不满足上一条,则检查剩余部分是否只包含特殊字符。为满足此条件,剩余部分必须非空,且不包含任何字母或数字。如果满足,则分类为 invalid
      3. 如果以上都不满足(例如,剩余部分混合了字母、数字或特殊字符),则分类为 miscellaneous
    • 如果首字符既非字母也非数字(即特殊字符):直接分类为 miscellaneous
  3. 实现细节:为了判断ID剩余部分的字符构成,我们可以遍历这部分子串,统计其中是否包含字母、数字或特殊字符,然后根据这些信息进行判断。Python中的 str.isdigit(), str.isalpha(), str.isalnum() 等方法可以简化这个过程。

这个逻辑覆盖了所有情况,并且通过检查顺序保证了规则的优先级。

代码

#include <iostream>
#include <string>
#include <vector>
#include <cctype>

using namespace std;

// 检查字符串是否只包含数字
bool is_all_digits(const string& s) {
    if (s.empty()) return false;
    for (char c : s) {
        if (!isdigit(c)) return false;
    }
    return true;
}

// 检查字符串是否只包含字母
bool is_all_letters(const string& s) {
    if (s.empty()) return false;
    for (char c : s) {
        if (!isalpha(c)) return false;
    }
    return true;
}

// 检查字符串是否只包含字母和数字
bool is_all_alnum(const string& s) {
    if (s.empty()) return true; // 空串也算
    for (char c : s) {
        if (!isalnum(c)) return false;
    }
    return true;
}

// 检查字符串是否只包含特殊字符
bool is_all_special(const string& s) {
    if (s.empty()) return false;
    for (char c : s) {
        if (isalnum(c)) return false;
    }
    return true;
}

string classify(const string& id) {
    if (id.length() < 2) {
        return "miscellaneous";
    }

    char first = id[0];
    string rest = id.substr(1);

    if (isalpha(first)) {
        if (is_all_digits(rest)) {
            return "electronics";
        }
        if (is_all_alnum(rest)) {
            return "accessories";
        }
    } else if (isdigit(first)) {
        if (is_all_letters(rest)) {
            return "clothing";
        }
        if (is_all_special(rest)) {
            return "invalid";
        }
    }
    
    return "miscellaneous";
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    while (n--) {
        string id;
        cin >> id;
        cout << classify(id) << endl;
    }

    return 0;
}
import java.util.Scanner;

public class Main {
    public static boolean isAllDigits(String s) {
        if (s.isEmpty()) return false;
        for (char c : s.toCharArray()) {
            if (!Character.isDigit(c)) return false;
        }
        return true;
    }

    public static boolean isAllLetters(String s) {
        if (s.isEmpty()) return false;
        for (char c : s.toCharArray()) {
            if (!Character.isLetter(c)) return false;
        }
        return true;
    }
    
    public static boolean isAllAlnum(String s) {
        if (s.isEmpty()) return true;
        for (char c : s.toCharArray()) {
            if (!Character.isLetterOrDigit(c)) return false;
        }
        return true;
    }

    public static boolean isAllSpecial(String s) {
        if (s.isEmpty()) return false;
        for (char c : s.toCharArray()) {
            if (Character.isLetterOrDigit(c)) return false;
        }
        return true;
    }

    public static String classify(String id) {
        if (id == null || id.length() < 2) {
            return "miscellaneous";
        }

        char first = id.charAt(0);
        String rest = id.substring(1);

        if (Character.isLetter(first)) {
            if (isAllDigits(rest)) {
                return "electronics";
            }
            if (isAllAlnum(rest)) {
                return "accessories";
            }
        } else if (Character.isDigit(first)) {
            if (isAllLetters(rest)) {
                return "clothing";
            }
            if (isAllSpecial(rest)) {
                return "invalid";
            }
        }
        
        return "miscellaneous";
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        for (int i = 0; i < n; i++) {
            String id = sc.next();
            System.out.println(classify(id));
        }
    }
}
import sys

def classify(id_str):
    if len(id_str) < 2:
        return "miscellaneous"

    first = id_str[0]
    rest = id_str[1:]

    if first.isalpha():
        # 检查剩余部分是否全为数字
        if rest.isdigit():
            return "electronics"
        # 检查剩余部分是否只包含字母和数字
        elif rest.isalnum():
            return "accessories"
            
    elif first.isdigit():
        # 检查剩余部分是否全为字母
        if rest.isalpha():
            return "clothing"
        
        # 检查剩余部分是否全为特殊字符
        is_all_special = True
        for char in rest:
            if char.isalnum():
                is_all_special = False
                break
        if is_all_special:
            return "invalid"
            
    # 其他所有情况
    return "miscellaneous"

def solve():
    try:
        n_str = sys.stdin.readline()
        if not n_str: return
        n = int(n_str)
        for _ in range(n):
            line = sys.stdin.readline().strip()
            print(classify(line))
    except (IOError, ValueError):
        return

solve()

算法及复杂度

  • 算法:字符串模拟 / 规则判断
  • 时间复杂度,其中 是第 个ID的长度。我们需要遍历每个ID字符串一次来判断其字符构成。
  • 空间复杂度,其中 是最长的ID字符串的长度,用于存储输入的字符串。