L1-016 查验身份证(15分)[java][python]

4 阅读3分钟

题目编号:L1-016
分数:15分
语言:Java、Python

题目描述

身份证号码由17位数字和1位校验码组成。校验码可以是数字0-9,也可以是字符X。现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。

输入格式

输入第一行给出正整数N(≤100),是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。

输出格式

按照输入的顺序每行输出1个有问题的身份证号码。如果所有号码都正常,则输出 All passed

输入样例

4
32012419880824156X
150404198708230612
120106197711022145
330702197712032113X

输出样例

150404198708230612
120106197711022145

解题思路

身份证校验码计算方法:前17位分别乘以对应系数并求和,结果对11取余得到余数,再通过余数表映射到校验码。

加权因子{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}

校验码映射表{'0':'1','1':'0','2':'X','3':'9','4':'8','5':'7','6':'6','7':'1','8':'0','9':'3','10':'2'}

关键点:

  • 前17位必须全为数字
  • 计算加权求和后取模11得到余数
  • 将余数映射为校验码,与输入的第18位比对
  • Python 中用字典做映射更简洁

代码实现

Java 实现

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] weight = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        char[] check = {'1', '0', 'X', '9', '8', '7', '6', '1', '0', '3', '2'};

        int n = sc.nextInt();
        boolean hasError = false;

        for (int i = 0; i < n; i++) {
            String id = sc.next();
            boolean valid = true;

            if (id.length() != 18) {
                valid = false;
            } else {
                int sum = 0;
                for (int j = 0; j < 17; j++) {
                    char c = id.charAt(j);
                    if (c < '0' || c > '9') {
                        valid = false;
                        break;
                    }
                    sum += (c - '0') * weight[j];
                }
                if (valid) {
                    char expect = check[sum % 11];
                    if (expect != id.charAt(17)) {
                        valid = false;
                    }
                }
            }

            if (!valid) {
                System.out.println(id);
                hasError = true;
            }
        }

        if (!hasError) {
            System.out.println("All passed");
        }
    }
}

Python 实现

weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
check_map = ['1', '0', 'X', '9', '8', '7', '6', '1', '0', '3', '2']

n = int(input())
has_error = False

for _ in range(n):
    id = input().strip()
    valid = True

    if len(id) != 18 or not id[:17].isdigit():
        valid = False
    else:
        s = sum(int(id[j]) * weight[j] for j in range(17))
        if check_map[s % 11] != id[17]:
            valid = False

    if not valid:
        print(id)
        has_error = True

if not has_error:
    print("All passed")

运行验证

输入:

4
32012419880824156X
150404198708230612
120106197711022145
330702197712032113X

输出:

150404198708230612
120106197711022145

与样例一致,通过验证。

复杂度分析

  • 时间复杂度:O(N × 17),N ≤ 100
  • 空间复杂度:O(1)

总结

本题考察字符串处理和固定规则校验。核心是严格按照加权因子求和取模映射来验证校验码。注意第18位可以是数字或字符X。