华为OD机试真题C卷-篇2

本文详细讨论了多任务排序算法,包括依赖关系管理和字符串匹配问题(如有效子串、最长子串、最短路径),还涉及手机应用防沉迷系统和基于IP定位的城市查询,以及文件缓存的管理和更新策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

启动多任务排序

  • A任务依赖B任务,执行时需要先执行B任务,完成后才可以执行A任务;
  • 若一个任务不依赖其他任务,则可以立即执行,多个同时执行的任务按照字母顺序A-Z排序;
  • 若B依赖A,C依赖A,D依赖B、C、E,则任务执行顺序为A、E、B、C、D;AE是同时执行且按照字母顺序;
    输入描述:
    多个任务的依赖关系;如A->B A依赖B,多组依赖关系用空格隔开
    输出描述:
    任务执行顺序,多个任务用空格隔开

示例1
输入:
A->B C->B
输出:
B A C

示例2
输入:
B->A C->A D->B D->C D->E
输出:
A E B C D

示例3
输入:
B->A E->A D->A E->D C->B F->B
输出:
A B D C E F

示例4
输入:
B->A C->A D->G E->F F->G
输出:
A G B C D F E

思路:

  • 迭代处理依赖关系列表,当没有依赖关系时(列表为空),所有的任务可以同时执行,只需按照字母顺序排序即可;
  • 每个依赖关系字符串使用 ‘->’ 分割出主动依赖的任务,被依赖的任务
    • 主动依赖的任务放入一个集合depending_tasks;
    • 被动依赖的任务放入一个集合depended_tasks;
    • 两个集合的并集为所有的任务(all_tasks 集合);
    • 两个集合的差集(depended_tasks - depending_tasks)为独立的任务,独立的任务可以立即执行,并按照字母顺序排序;
  • 将可以立即执行的任务排序后放入task_run_order列表,并重新过滤依赖关系列表(若依赖的任务已经执行,则删除该依赖关系)
  • 继续迭代处理剩余的依赖关系列表,直至其为空,此时剩余的任务(all_tasks - task_run_order)不再有依赖关系,可以同时执行,并按照字母顺序排序即可,最后加入task_run_order列表。
  • 返回task_run_order
# __author__ = "laufing"
from typing import List


class SortTask:
    def solution(self, dependent_relations: List[str]):
        # 迭代
        task_run_order = []
        pre_run_tasks = set()
        # 所有的任务
        all_tasks = set()

        while dependent_relations:
            # 主动依赖其他任务的任务
            depending_tasks = set()
            # 被依赖的任务
            depended_tasks = set()
            for relation in dependent_relations:
                # 任务分割 前者主动依赖  后者被动依赖
                task_a, task_b = relation.split("->")

                if task_a not in depending_tasks:
                    depending_tasks.add(task_a)
                if task_b not in depended_tasks:
                    depended_tasks.add(task_b)

            print("depending:", depending_tasks)
            print("depended:", depended_tasks)
            if not all_tasks:
                all_tasks = depending_tasks | depended_tasks
			if pre_run_tasks:
				task_run_order.extend(sorted(list(pre_run_tasks-depending_tasks)))
				pre_run_tasks.clear()
            # 获取不依赖其他任务的 任务(独立的)
            # 独立的任务可以立即执行(注意按字母顺序排序)
            independent_tasks = depended_tasks - depending_tasks
            task_run_order.extend(sorted(list(independent_tasks)))
            
            # 处理依赖关系
            temp_relations = []
            for relation in dependent_relations:
            	if relation[-1] in task_run_order:
            		pre_run_tasks.add(relation[0])
            	else:
            		temp_relations.append(relation)
			dependent_relations = temp_relations
        # 依赖关系解决完后,执行剩余的任务
        task_run_order.extend(sorted(list(all_tasks - set(task_run_order))))
		
		# 任务去重
		result = []
		for i in task_run_order:
			if i not in result:
				result.append(i)
        return result


if __name__ == '__main__':
    sort_task = SortTask()
    while True:
        try:
            # 输入
            lay_relations = input("lay:").strip().split()
            print("origin relations:", lay_relations)
            # 解决方案
            result = sort_task.solution(lay_relations)
            # 输出结果
            print(" ".join(result))
        except KeyboardInterrupt:
            break

 

有效子字符串

  • 输入两个字符串S、L, len(S)<=100, len(L)<=500000;
  • 判断S是否是L的有效子字符串;
  • 判断规则:S中的每个字符在L中存在,且保持与S中一致的顺序;
    输入描述:
    一行输入S
    一行输入L,只包含小写字母
    输出描述:
    S最后一个有效字符在L中的索引位置,无有效字符则输出-1

示例1
输入:
ace
abcde
输出:
4

示例2
输入:
fgh
abcde
输出:
-1

思路:

  • 索引遍历字符串S,依次在temp_l_str中查找 (find方法);
  • 使用valid_pos (元组)列表,存储S中每个字符在L中的位置,如[(‘a’, 0)];
  • 从L中每次找到的当前位置分片pre字符串,temp_l_str 两部分,迭代从temp_l_str继续查找S中的下一个字符,找到的索引位置+len(pre) ,然后存入valid_pos,未找到则继续下一次迭代;
  • 若valid_pos为空,则输出-1
  • 若valid_pos非空,则输出valid_pos[-1][1]
# __author__ = "laufing"


class ValidSubString:
    def solution(self, s_str, l_str):
        # S中字符的有效位置
        valid_pos = []
        s_str_length = len(s_str)
        # 前部分
        pre = ""
        # 后部分
        temp_l_str = l_str[:]
        for i in range(s_str_length):

            pos = temp_l_str.find(s_str[i])
            if pos != -1:  # 找到
                # 恢复在l_str中的位置
                pos = len(pre) + pos
                valid_pos.append((s_str[i], pos))
                # 重新分割
                pre = l_str[:pos+1]
                temp_l_str = l_str[pos+1:]

            if not temp_l_str:
                break
        if valid_pos:
            print(valid_pos[-1][1])
            return valid_pos[-1][1]

        print(-1)
        return -1


if __name__ == '__main__':
    valid_sub_str = ValidSubString()
    while True:
        try:
            s = input("s:").strip()
            l = input("l:").strip()
            result = valid_sub_str.solution(s, l)

        except KeyboardInterrupt:
            break

其他思路:

import functools
class TreeNode:
    def __init__(self, left, right, weight, height):
        self.left = left
        self.right = right
        self.weight = weight
        self.height = height
 
 
s_arr = input()
l_arr = input()
index1 = 0
index2 = 0
 
while (index1 < len(s_arr) and index2 < len(l_arr)) :
    if (s_arr[index1] == l_arr[index2]) :
        index1+=1
    
    index2+=1
 
if(index1 == len(s_arr)):
    print(index2 - 1)
else:
    print(-1)

最长子字符串的长度

  • 给一个字符串s, 它的首尾相连成一个环;
  • 在环中找出‘o’字符出现了偶数次的最长子串的长度;
    输入描述:
    小写字母组成的字符串
    输出描述
    一个整数

示例1
输入:
alolobo
输出:
6
说明,最长子串之一是‘alolob’,包含两个‘o’

示例2
输入:
looxdolx
输出:
7

示例3
输入:
bcbcbc
输出:
6

import functools
import sys
from collections import Counter
 
s = input()
s_slices = Counter(s)
num = s_slices.get("o",0)
print(len(s) - 1 if num % 2 else len(s))

 

最长子字符串的长度(二)

  • 在上一题的基础上,在环中找出l、o、x字符都出现了偶数次的最长子串的长度;
    示例1
    输入:
    alolobo
    输出:
    6
    说明, 最长子串之一alolobo,包含l/o各两个,x 是0个

示例2
输入:
bcbcbc
输出:
7

 
def findTheLongestSubstring(s) :
    dp = [[] for i in range(8)]
    dp[0].append(-1)
    pattern = 0
    res = 0
    for i in range(len(s)):
        if s[i] == 'l':
            pattern^= (1<<0)
        elif s[i] == 'o':
            pattern^= (1<<1)
        elif s[i] == 'x':
            pattern^= (1<<2)
        current = dp[pattern]
        current.append(i)
        #长度不能超过n
        while(True):
            if(current[-1] - current[0] <= len(s)/2):
                break
            current.pop(0)
        if(res < current[-1] - current[0]):
            res = current[-1] - current[0]
    return res
 
input_str = input()
print(findTheLongestSubstring(input_str+input_str))          

 

两个字符串间的最短路径问题(2xx)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


result = float('inf')
input_strs = input().split(" ")
str1 = input_strs[0]
str2 = input_strs[1]
n = len(str1)
m = len(str2)
 
visited = [[0 for i in range(m+2)] for j in range(n+2)]
lst = []
lst.append([-1, -1, 0])
while (True):
    if(len(lst)<=0) :
        print(result)
        break
    else :
        current = lst[0]
        lst.pop(0)
        if (current[0] +1 == n) :  
            if(current[2] - current[1] + m - 1 < result) :
                result = current[2] - current[1] + m - 1
            
            continue
        
        if (current[1] +1 == m) :  
            if(current[2] - current[0] + n - 1 < result) :
                result = current[2] - current[0] + n - 1
            
            continue
        
        if (str1[current[0]+1] == str2[current[1]+1]) : 
            if (visited[current[0] + 2][current[1]+2] == 0) :  
                visited[current[0] + 2][current[1]+2] = 1
                lst.append([current[0] + 1, current[1]+1, current[2] + 1]) 
            
        else :  
            if (visited[current[0] + 2][current[1]+1] == 0) : 
                visited[current[0] + 2][current[1]+1] = 1
                lst.append([current[0] + 1, current[1], current[2] + 1])  
            
            if (visited[current[0] + 1][current[1]+2] == 0) :  
                visited[current[0] + 1][current[1]+2] = 1
                lst.append([current[0], current[1]+1, current[2] + 1])  
                    
                          

 

中文分词模拟器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


import re
import math
import sys
from queue import Queue
 
target_words = input().split(",")
target_len = []
for x in target_words:
    target_len.append(len(x))
 
words = input().split(",")
words_len = []
for x in words:
    words_len.append(len(x))
 
result = ""
k=0
flag = False
while(True):
    if(k>=len(target_words)):
        break
    else :
        dp = [0 for i in range(target_len[k] + 1)] 
        dp[target_len[k]] = 1 
        i = target_len[k] 
        while(i>=0):
            for j in range(len(words)):
                if(i + len(words[j]) <= target_len[k]) :
                    split_str=target_words[k][i: i + len(words[j])]
                    if (dp[i + len(words[j])]==1 and split_str==words[j]) : 
                        dp[i] = 1 
                        break
            i-=1
            
        if (dp[0]!=0) : 
            temp_res = ""
            i = 0
            while (True) :
                if(i >= target_len[k]):
                    break
                else :
                    pos = -1 
                    for j in range(len(words)):
                        if (i + words_len[j] <= target_len[k]):
                            split_str=target_words[k][i: i + len(words[j])]
                            if(split_str == words[j]
                                and dp[i + words_len[j]]==1 and words_len[j] > pos) :
                                pos = words_len[j]
 
                    temp_res += target_words[k][i: i + pos] + ","
                    i += pos
            result += temp_res
        else :
            outut_str=""
            for i in range(len(target_len[k])):
                outut_str += char_arr[i]
                if(i!=len(char_arr)-1):
                    outut_str +=","
                
            flag = True
    k+=1
    
if(not flag):
    print(result[:-1])

 

手机App防沉迷系统

在这里插入图片描述
在这里插入图片描述

 
 
apps = []
def transfer(input_str):
    nums = [int(x) for x in input_str.split(":")]
    total = 60*nums[0] + nums[1]
    return str(total)
 
 
def solve(infos) :
    global apps
    new_apps = []
    for app in apps:
        if (not (app[2]<=infos[3] and app[3]>=infos[2] and app[1] < infos[1])) :
            new_apps.append(app);
    apps = new_apps;
    
  
    flag = False
    for i in range(len(apps)):
        if (apps[i][2]<=infos[3] and apps[i][3]>=infos[2] and apps[i][1] >= infos[1]) :
          flag = True
    if (not flag) :
        apps.append(infos)
 
n = int(input())
for i in range(n):
    infos = input().split(" ")
    infos[2] = transfer(infos[2])
    infos[3] = transfer(infos[3])
 
    solve(infos)
 
target = transfer(input())
output_str = "NA"
for i in range(len(apps)):
    if (target>=apps[i][2] and target<=apps[i][3]) :
        output_str = apps[i][0]
        break
print(output_str)

 

根据IP查找城市

在这里插入图片描述
在这里插入图片描述

 
def transfer(ip_str) :
    ips = [int(x) for x in ip_str.split(".")]
    result = 0
    for i in range(4):
        result = result * 256  
        result |= ips[i]
    return result
    
 
city_str = input().split(";") 
target_ip = input().split(",") 
ip_ranges = {}
for i in range(len(city_str)):
    ranges = city_str[i].split("=")[1].split(",") 
    if city_str[i].split("=")[0] in ip_ranges:
        ip_ranges[city_str[i].split("=")[0]].append([transfer(ranges[0]), transfer(ranges[1])])
    else:
        ip_ranges[city_str[i].split("=")[0]] = []
        ip_ranges[city_str[i].split("=")[0]].append([transfer(ranges[0]), transfer(ranges[1])])
 
 
output_str = ""
i=0
while(True):
    if(i>=len(target_ip)):
        break
    else :
        target_num = transfer(target_ip[i]) 
        target_city = "" 
        size = float('inf')
 
        for j in range(len(city_str)):
            ranges = ip_ranges[city_str[j].split("=")[0]]
            for k in range(len(ranges)):
                start = ranges[k][0]
                end = ranges[k][1]
                if (target_num >= start and target_num <= end) :
                    if (end - start < size) :
                        target_city = city_str[j].split("=")[0]
                        size = end - start
        output_str+=target_city+","
    
    i+=1
 
if(len(output_str) > 0):
    output_str= output_str[:-1]
print(output_str)

 

文件缓存系统

在这里插入图片描述
在这里插入图片描述

 
files= {}
total_value = 0
times = 1
m = int(input())
n = int(input())
for i in range(n):
    operations = input().split(" ")
    if (operations[0]=="get") :
        if(operations[1] in files) :
            file_info = files[operations[1]]
            file_info[1]+=1
            file_info[2] = times
            times += 1
            files[operations[1]] = file_info
        else :
            continue
    else :
        if( operations[1] not in files) :
            file_size = int(operations[2])
            if (total_value + file_size > m) :
                my_list = []
                for x in files:
                    my_list.append([x, files[x]])
                my_list = sorted(my_list, key=lambda x:(x[1][1], x[1][2]))
        
                for j in range(len(my_list)):
                    single_file = my_list[j]
                    if (total_value + single_file[1][0] >= m) :
                        files.pop(single_file[0])
                        total_value = total_value - single_file[1][0]
                    else :
                        break
 
            
            if (total_value + file_size <= m) :
                total_value += file_size
                files[operations[1]] =  [file_size, 0, times]
                times += 1
            
if (len(files)==0) :
    print("NONE")
else :
    
    my_list = []
    for x in files:
        my_list.append(x)
    
    my_list.sort()
    output_str= ""
    for i in range(len(my_list)):
        output_str += my_list[i]
        if(i!=len(my_list)-1):
            output_str += ","
        
    print(output_str)  
            

 

### 华为OD分糖果问Python思路 #### 问描述 小明从糖果盒中随意抓取一定数量的糖果,每次可以执行三种操作之一:取出一半糖果并舍去余数;如果当前糖果数目为奇数,则可以从盒子中再拿一个糖果或将手里的一个糖果放回去。目标是最少经过几次这样的操作能够使手中的糖果变为一颗。 为了达到这个目的,采用贪心策略来解决问[^3]。具体来说,在每一步都尽可能快速地减少糖果的数量直到只剩下一颗为止。当遇到奇数个糖果时,优先考虑加一而不是减一,因为这样可以在下一轮更有效地通过除以2的方式大量削减糖果总数。 #### 贪婪算法分析 对于任意正整数n表示初始糖果数: - 如果 n 是偶数,则直接将其除以2- 若 n 为奇数,则判断 (n+1)/2 和 (n−1)/2 的大小关系,选择较小的那个作为下一步的结果,这是因为我们希望更快接近1。 这种做法基于这样一个事实——当我们面对两个连续的奇数值时,较大的那个总是可以通过增加1变成一个小得多的新值(即其半数),而较小的一个则需要两次操作才能完成同样的效果(先减后除)[^4]。 #### Python代码实现 下面给出了解决上述问的具体Python程序: ```python def min_steps_to_one(n): steps = 0 while n != 1: if n % 2 == 0: n //= 2 elif ((n + 1) // 2) < ((n - 1) // 2): n += 1 else: n -= 1 steps += 1 return steps if __name__ == "__main__": candy_count = int(input().strip()) print(min_steps_to_one(candy_count)) ``` 此函数接收一个参数`n`代表起始的糖果数量,并返回将这些糖果减少到只有一个所需的最小步数。主程序部分读入用户输入的数据并调用该方法打印最终结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值