题目## 题目
解题思路
这是一个字符串处理和验证问题。具体要求:
- 验证手机号是否合法,需要满足:
- 长度为11位数字
- 前三位为指定的运营商号段
- 根据号段判断运营商:
- 电信:133,153,180,181,189
- 联通:130,131,155,185,186
- 移动:135,136,150,182,188
- 输出对应运营商名称,非法号码输出-1
代码
#include <iostream>
#include <string>
#include <unordered_set>
using namespace std;
class PhoneValidator {
private:
// 运营商号段集合
unordered_set<string> telecom {"133", "153", "180", "181", "189"};
unordered_set<string> unicom {"130", "131", "155", "185", "186"};
unordered_set<string> mobile {"135", "136", "150", "182", "188"};
public:
string validate(string phone) {
// 检查长度
if (phone.length() != 11) {
return "-1";
}
// 获取前三位
string prefix = phone.substr(0, 3);
// 判断运营商
if (telecom.count(prefix)) {
return "China Telecom";
}
if (unicom.count(prefix)) {
return "China Unicom";
}
if (mobile.count(prefix)) {
return "China Mobile Communications";
}
return "-1";
}
};
int main() {
int t;
cin >> t;
PhoneValidator validator;
while (t--) {
string phone;
cin >> phone;
cout << validator.validate(phone) << endl;
}
return 0;
}
import java.util.*;
public class Main {
// 运营商号段集合
private static final Set<String> telecom = new HashSet<>(Arrays.asList(
"133", "153", "180", "181", "189"));
private static final Set<String> unicom = new HashSet<>(Arrays.asList(
"130", "131", "155", "185", "186"));
private static final Set<String> mobile = new HashSet<>(Arrays.asList(
"135", "136", "150", "182", "188"));
public static String validate(String phone) {
// 检查长度
if (phone.length() != 11) {
return "-1";
}
// 获取前三位
String prefix = phone.substring(0, 3);
// 判断运营商
if (telecom.contains(prefix)) {
return "China Telecom";
}
if (unicom.contains(prefix)) {
return "China Unicom";
}
if (mobile.contains(prefix)) {
return "China Mobile Communications";
}
return "-1";
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- > 0) {
String phone = sc.next();
System.out.println(validate(phone));
}
}
}
def validate_phone(phone: str) -> str:
# 运营商号段集合
telecom = {'133', '153', '180', '181', '189'}
unicom = {'130', '131', '155', '185', '186'}
mobile = {'135', '136', '150', '182', '188'}
# 检查长度
if len(phone) != 11:
return "-1"
# 获取前三位
prefix = phone[:3]
# 判断运营商
if prefix in telecom:
return "China Telecom"
if prefix in unicom:
return "China Unicom"
if prefix in mobile:
return "China Mobile Communications"
return "-1"
def main():
t = int(input())
for _ in range(t):
phone = input().strip()
print(validate_phone(phone))
if __name__ == "__main__":
main()
算法及复杂度
- 算法:字符串处理 + 集合查找
- 时间复杂度: O ( T ) \mathcal{O}(T) O(T) - T T T 为测试用例数量,每次验证为 O ( 1 ) \mathcal{O}(1) O(1)
- 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1) - 只需要存储固定的号段集合
解题思路
这是一个贪心算法问题。需要找到能保证配对成功的最少手套数量,需要考虑单边缺失和双边都有的情况。
关键点:
- 区分单边缺失和双边都有的情况
- 记录每边手套的总数和最小值
- 贪心选择较少的一边
- 考虑配对成功的必要条件
算法步骤:
- 处理单边缺失的手套
- 统计双边都有时的手套数量
- 计算最优选择策略
- 确保能够配对成功
代码
class Gloves {
public:
int findMinimum(int n, vector<int> left, vector<int> right) {
int leftSum = 0, leftMin = INT_MAX;
int rightSum = 0, rightMin = INT_MAX;
int ret = 0;
// 遍历所有颜色的手套
for(int i = 0; i < n; ++i) {
if(left[i] == 0 || right[i] == 0) {
// 单边缺失的情况,必须全部拿走
ret += left[i] + right[i];
} else {
// 双边都有的情况,更新总数和最小值
leftMin = min(leftMin, left[i]);
rightMin = min(rightMin, right[i]);
leftSum += left[i];
rightSum += right[i];
}
}
// 选择较少的一边,并确保能配对成功
ret += min(leftSum - leftMin + 1, rightSum - rightMin + 1) + 1;
return ret;
}
};
public class Gloves {
public int findMinimum(int n, int[] left, int[] right) {
int leftSum = 0, leftMin = Integer.MAX_VALUE;
int rightSum = 0, rightMin = Integer.MAX_VALUE;
int ret = 0;
// 遍历所有颜色的手套
for(int i = 0; i < n; i++) {
if(left[i] == 0 || right[i] == 0) {
// 单边缺失的情况,必须全部拿走
ret += left[i] + right[i];
} else {
// 双边都有的情况,更新总数和最小值
leftMin = Math.min(leftMin, left[i]);
rightMin = Math.min(rightMin, right[i]);
leftSum += left[i];
rightSum += right[i];
}
}
// 选择较少的一边,并确保能配对成功
ret += Math.min(leftSum - leftMin + 1, rightSum - rightMin + 1) + 1;
return ret;
}
}
# -*- coding:utf-8 -*-
class Gloves:
def findMinimum(self, n, left, right):
leftSum, leftMin = 0, float('inf')
rightSum, rightMin = 0, float('inf')
ret = 0
# 遍历所有颜色的手套
for i in range(n):
if left[i] == 0 or right[i] == 0:
# 单边缺失的情况,必须全部拿走
ret += left[i] + right[i]
else:
# 双边都有的情况,更新总数和最小值
leftMin = min(leftMin, left[i])
rightMin = min(rightMin, right[i])
leftSum += left[i]
rightSum += right[i]
# 选择较少的一边,并确保能配对成功
ret += min(leftSum - leftMin + 1, rightSum - rightMin + 1) + 1
return ret
算法及复杂度
- 算法:贪心算法
- 时间复杂度: O ( n ) \mathcal{O(n)} O(n),只需遍历一次数组
- 空间复杂度: O ( 1 ) \mathcal{O(1)} O(1),只需要常数级额外空间
986

被折叠的 条评论
为什么被折叠?



