校招算法笔面试 | 华为机试-合法IP

华为机试:合法IP判断与贪心算法题解

题目## 题目

题目链接

解题思路

  1. 对于每个字符串,统计每个字母出现的次数
  2. 将字母出现次数按从大到小排序
  3. 贪心策略:将最大的次数分配最大的漂亮度(26),次大的分配次大的漂亮度(25),以此类推
  4. 计算总的漂亮度值

代码

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

int getBeauty(string& name) {
    vector<int> count(26, 0);  // 统计26个字母出现次数
    
    // 统计每个字母出现的次数
    for(char c : name) {
        count[tolower(c) - 'a']++;
    }
    
    // 将出现次数从大到小排序
    sort(count.begin(), count.end(), greater<int>());
    
    // 计算漂亮度
    int beauty = 0;
    int value = 26;  // 最大漂亮度从26开始
    for(int i = 0; i < 26 && count[i] > 0; i++) {
        beauty += count[i] * value--;
    }
    
    return beauty;
}

int main() {
    int n;
    cin >> n;
    
    while(n--) {
        string name;
        cin >> name;
        cout << getBeauty(name) << endl;
    }
    
    return 0;
}
import java.util.*;

public class Main {
    public static int getBeauty(String name) {
        int[] count = new int[26];
        
        // 统计每个字母出现的次数
        for(char c : name.toLowerCase().toCharArray()) {
            count[c - 'a']++;
        }
        
        // 将出现次数从大到小排序
        Arrays.sort(count);
        
        // 计算漂亮度
        int beauty = 0;
        int value = 26;
        for(int i = 25; i >= 0 && count[i] > 0; i--) {
            beauty += count[i] * value--;
        }
        
        return beauty;
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        while(n-- > 0) {
            String name = sc.next();
            System.out.println(getBeauty(name));
        }
    }
}
def get_beauty(name):
    # 统计每个字母出现的次数
    count = {}
    for c in name.lower():
        count[c] = count.get(c, 0) + 1
    
    # 将出现次数从大到小排序
    freq = sorted(count.values(), reverse=True)
    
    # 计算漂亮度
    beauty = 0
    value = 26
    for f in freq:
        beauty += f * value
        value -= 1
    
    return beauty

n = int(input())
for _ in range(n):
    name = input().strip()
    print(get_beauty(name))

算法及复杂度

  • 算法:贪心算法
  • 时间复杂度: O ( L + K log ⁡ K ) \mathcal{O}(L + K\log K) O(L+KlogK),其中 L L L 是字符串长度, K K K 是不同字符的数量(最大为26)
  • 空间复杂度: O ( K ) \mathcal{O}(K) O(K),需要存储每个字符的出现次数(最大为26)

题目链接

解题思路

这是一个判断IP地址是否合法的问题。需要检查以下几个方面:

关键规则

  1. IP地址格式:

    • 由4个部分组成,每部分8位
    • 用点分隔,如:10.137.17.1
    • 每部分都是无符号整数
  2. 合法性要求:

    • 每部分范围:0~255
    • 不能有空格
    • 不能有前导零
    • 必须是4个部分

实现思路

  1. 输入处理:

    • 按点分割字符串
    • 检查分割后的部分数量
  2. 合法性检查:

    • 检查每部分是否为数字
    • 检查数值范围
    • 检查前导零

代码

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Solution {
public:
    bool isValidIP(string ip) {
        // 分割IP地址
        vector<string> parts;
        string part;
        for (char c : ip) {
            if (c == '.') {
                if (part.empty()) return false;
                parts.push_back(part);
                part.clear();
            } else {
                part += c;
            }
        }
        if (!part.empty()) parts.push_back(part);
        
        // 检查部分数量
        if (parts.size() != 4) return false;
        
        // 检查每个部分
        for (string& p : parts) {
            // 检查长度
            if (p.empty() || p.length() > 3) return false;
            
            // 检查前导零
            if (p.length() > 1 && p[0] == '0') return false;
            
            // 检查是否为数字
            for (char c : p) {
                if (!isdigit(c)) return false;
            }
            
            // 检查范围
            int num = stoi(p);
            if (num < 0 || num > 255) return false;
        }
        
        return true;
    }
};

int main() {
    string ip;
    while (cin >> ip) {
        Solution sol;
        cout << (sol.isValidIP(ip) ? "YES" : "NO") << endl;
    }
    return 0;
}
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            String ip = sc.next();  // 使用next()而不是nextLine()
            System.out.println(isValidIP(ip) ? "YES" : "NO");
        }
    }
    
    public static boolean isValidIP(String ip) {
        // 检查是否包含空格
        if (ip.contains(" ")) return false;
        
        // 分割IP地址
        String[] parts = ip.split("\\.");
        
        // 检查部分数量
        if (parts.length != 4) return false;
        
        // 检查每个部分
        for (String part : parts) {
            // 检查长度
            if (part.isEmpty() || part.length() > 3) return false;
            
            // 检查前导零
            if (part.length() > 1 && part.charAt(0) == '0') return false;
            
            // 检查是否为数字
            for (char c : part.toCharArray()) {
                if (!Character.isDigit(c)) return false;
            }
            
            // 检查范围
            try {
                int num = Integer.parseInt(part);
                if (num < 0 || num > 255) return false;
            } catch (NumberFormatException e) {
                return false;
            }
        }
        
        // 检查原始字符串中的点的数量(避免多余的点)
        int dotCount = 0;
        for (char c : ip.toCharArray()) {
            if (c == '.') dotCount++;
        }
        if (dotCount != 3) return false;
        
        return true;
    }
}
def isValidIP(ip):
    # 分割IP地址
    parts = ip.split('.')
    
    # 检查部分数量
    if len(parts) != 4:
        return False
        
    # 检查每个部分
    for part in parts:
        # 检查长度
        if not part or len(part) > 3:
            return False
            
        # 检查前导零
        if len(part) > 1 and part[0] == '0':
            return False
            
        # 检查是否为数字
        if not part.isdigit():
            return False
            
        # 检查范围
        num = int(part)
        if num < 0 or num > 255:
            return False
            
    return True

# 主程序
while True:
    try:
        ip = input().strip()
        print("YES" if isValidIP(ip) else "NO")
    except:
        break

算法及复杂度

算法分析

  1. 字符串分割:

    • 按点分割字符串
    • 检查分割后的部分
  2. 数值检查:

    • 检查数字有效性
    • 检查范围合法性
    • 检查格式规范

复杂度分析

  • 时间复杂度: O ( n ) \mathcal{O}(n) O(n) - 其中 n n n 是IP地址的长度
  • 空间复杂度: O ( n ) \mathcal{O}(n) O(n) - 需要存储分割后的字符串
专业面试我的技巧和经验: 一、 巧妇难为无米之炊,事前做一些功课是必须的,把自己学习过的和应聘岗位相关的内容复习下,比如性能与算法岗位:本科电子信息工程和通信工程这些课程肯定学过,通信原理,信息论和编码,信号与系统,数字信号处理,复习一下掌握大概的轮廓一个星期应该差不多可以搞定. 二、 善于引导面试官,比如当面试官问到什么问题不懂的时候,避免连问几个都不懂,可以尝这么说:我***方面的知识比较匮乏,不是很了解,但是我对***的知识还是比较熟习,我觉得***的知识在我们华为性能与算法工程师必须要掌握的吧。以我面试为例,面试问我3G和4G的关键技术,已经这些关键技术的基本原理,我是做雷达信号处理的,确实不懂。我就和面试官说:对不起,因为研究生期间主要做的雷达信号处理的工作,我对移动通信的知识了解甚少,但是我对移动通信的基础只是比如通信原理和调制解调技术还有一定的了解(当然这都是我事先复习好的),我觉得无论什么类型的通信技术都离不开这些基本的理论。接着面试官就让我说信源编码和信道编码的作用已经他们通常采用的方法,当然我也就能对答如流了。所以,引导很重要。 三、 专业面试对自己简历上不要为了蒙骗面试官,写的项目自己捡不熟悉,对简历上的东西一问三不知,语言表达不清楚,说不半天不能告诉面试官你做的工作内容和意义,这个很不好。 群面 一般10-14个人,看当天应聘的人数而定,分2组,一个话题,让排序之类的,或者辩论之类的,不同的组会抽到不同的问题,不同的地方也会有不同的问题,在这里把问题说出来没什么意义,这一轮会有很多意想不到的情况,比如这组我本来不是选为组长,但是在做总结的时候面试官让我做总结,或者突然问你刚才某某同学说的话你同意吗,或者突然说你今天脸色好像不好看之类的,所以灵应变才是王道。群面一般要自我介绍,自我介绍要简短,不要说太多,我建议按以下几个方面说,自己学专业、来自哪里、然后说自己学习,主要稍微说下自己的项目,说下名字就OK了,然后说自己做项目获得成果,比如发表文章,专利和之类的。然后说自己优点和缺点,一般情况下优点缺点都要说,而且我觉得最好优点缺点自己多准备几个,免得到时候你要说的前面的人都说了,就像我们这组:我开始说缺点的时候说我性格比较急,做什么事情都想快点做完,午觉也不睡,但是经常适得其反,中午不谁觉,下午就工作效率低。后面好几个同学说的时候都这么说了,惹的面试官说,你们重复一个东西说。说缺点的时候大家要慎重,不要说和自己工作相关的缺点,比如我们那个组一个同学说:我的缺点就是比较随性,重要场合经常穿拖鞋为此挨了不少批评。 面试官:。。。。(前面省略了一些),你这种随行的行为有同学提醒过你吗?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值