校招算法笔面试 | 校招笔面试真题-手机号

题目## 题目

题目链接

解题思路

这是一个字符串处理和验证问题。具体要求:

  1. 验证手机号是否合法,需要满足:
    • 长度为11位数字
    • 前三位为指定的运营商号段
  2. 根据号段判断运营商:
    • 电信:133,153,180,181,189
    • 联通:130,131,155,185,186
    • 移动:135,136,150,182,188
  3. 输出对应运营商名称,非法号码输出-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) - 只需要存储固定的号段集合

题目链接

解题思路

这是一个贪心算法问题。需要找到能保证配对成功的最少手套数量,需要考虑单边缺失和双边都有的情况。

关键点:

  1. 区分单边缺失和双边都有的情况
  2. 记录每边手套的总数和最小值
  3. 贪心选择较少的一边
  4. 考虑配对成功的必要条件

算法步骤:

  1. 处理单边缺失的手套
  2. 统计双边都有时的手套数量
  3. 计算最优选择策略
  4. 确保能够配对成功

代码

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),只需要常数级额外空间
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值