日常刷题(1)

1. 5键键盘

1.1. 题目描述

有一个特殊的5键键盘,上面有a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五个键。

a键在屏幕上输出一个字母a;

ctrl-c将当前选择的字母复制到剪贴板;

ctrl-x将当前选择的字母复制到剪贴板,并清空选择的字母;

ctrl-v将当前剪贴板里的字母输出到屏幕;

ctrl-a选择当前屏幕上的所有字母。

注意:

剪贴板初始为空,新的内容被复制到剪贴板时会覆盖原来的内容
当屏幕上没有字母时,ctrl-a无效
当没有选择字母时,ctrl-c和ctrl-x无效
当有字母被选择时,a和ctrl-v这两个有输出功能的键会先清空选择的字母,再进行输出
给定一系列键盘输入,输出最终屏幕上字母的数量。

1.2. 输入描述

输入为一行,为简化解析,用数字1 2 3 4 5代表a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五个键的输入,数字用空格分隔。
输出描述
输出一个数字,为最终屏幕上字母的数量。
在这里插入图片描述

1.3. 题目解析

逻辑题,主要考察多情况的处理。

题目中没有准确说明 选择状态 何时被解除,比如我ctrl-a全选所有字母时,然后ctrl-c将选择的字母复制到剪贴板,那么此时屏幕中字母的选中状态是保留还是清除呢?

我理解ctrl-x剪切走屏幕内容,没有字母了,自然就没有选中状态了。另外,a、ctrl-v输入时,如果有字母选中状态,则输入时会覆盖选中内容,那么选中状态就没了。

1.4. 代码

class FiveKeyboards:
    def __init__(self):
        self.selected = ''
        self.copyboard = ''
        self.op_map = {
            '1': self.a,
            '2': self.ctrl_c,
            '3': self.ctrl_x,
            '4': self.ctrl_v,
            '5': self.ctrl_a,
        }

    def a(self, string: str):
        if not self.selected:
            return string + 'a'

        return 'a'

    def ctrl_c(self, string: str):
        if not self.selected:
            return string

        self.copyboard = self.selected
        return string

    def ctrl_x(self, string: str):
        if not self.selected:
            return string

        self.copyboard = self.selected
        return ''

    def ctrl_v(self, string: str):
        if not self.selected:
            return string + self.copyboard

        self.selected = ''
        return self.copyboard

    def ctrl_a(self, string: str):
        self.selected = string
        return string

    def __call__(self, ops: str):
        # 用数字1 2 3 4 5代表a,ctrl-c,ctrl-x,ctrl-v,ctrl-a五个键的输入
        if '1' not in ops:
            return 0

        string = ''
        for op in ops:
            func = self.op_map.get(op)
            if not func:
                continue
            string = func(string)
            print(f"{func.__name__}: {string}")
        return len(string)

2. 爱吃蟠桃的孙悟空

2.1. 题目描述

孙悟空爱吃蟠桃,有一天趁着蟠桃园守卫不在来偷吃。已知蟠桃园有 N 棵桃树,每颗树上都有桃子,守卫将在 H 小时后回来。

孙悟空可以决定他吃蟠桃的速度K(个/小时),每个小时选一颗桃树,并从树上吃掉 K 个,如果树上的桃子少于 K 个,则全部吃掉,并且这一小时剩余的时间里不再吃桃。

孙悟空喜欢慢慢吃,但又想在守卫回来前吃完桃子。

请返回孙悟空可以在 H 小时内吃掉所有桃子的最小速度 K(K为整数)。如果以任何速度都吃不完所有桃子,则返回0。

2.2. 输入描述

第一行输入为 N 个数字,N 表示桃树的数量,这 N 个数字表示每颗桃树上蟠桃的数量。

第二行输入为一个数字,表示守卫离开的时间 H。

其中数字通过空格分割,N、H为正整数,每颗树上都有蟠桃,且 0 < N < 10000,0 < H < 10000。

2.3. 输出描述

吃掉所有蟠桃的最小速度 K,无解或输入异常时输出 0。

2.4. 用例

在这里插入图片描述

2.5. 题目解析

遍历吃桃速度,找到最小可行解。为了优化该操作可以采用二分法求解

2.6. 代码

class Peach:
    def can_finish(self, speed: int, tree_cnts: List[int], time_limit: int):
        cost = 0
        for tree_cnt in tree_cnts:
            cost += tree_cnt // speed + (tree_cnt % speed > 0)
        return cost <= time_limit

    def __call__(self, tree_cnts: List[int], time_limit: int):
        if len(tree_cnts) > time_limit:
            return 0

        max_speed = speed = max(tree_cnts)
        if len(tree_cnts) == time_limit:
            return max_speed

        min_speed = 1
        while min_speed < max_speed:
            mid_speed = (min_speed + max_speed) // 2

            if self.can_finish(mid_speed, tree_cnts, time_limit):
                speed = mid_speed
                max_speed = mid_speed - 1
            else:
                min_speed = mid_speed + 1
        return speed

3. 按身高和体重排队

3.1. 题目描述

某学校举行运动会,学生们按编号(1、2、3…n)进行标识,现需要按照身高由低到高排列,对身高相同的人,按体重由轻到重排列;对于身高体重都相同的人,维持原有的编号顺序关系。请输出排列后的学生编号。

3.2. 输入描述

两个序列,每个序列由n个正整数组成(0 < n <= 100)。第一个序列中的数值代表身高,第二个序列中的数值代表体重。

3.3. 输出描述

排列结果,每个数值都是原始序列中的学生编号,编号从1开始

3.4. 用例

在这里插入图片描述

3.5. 题目解析

多条件排序,sort大法

3.6. 代码

class OrderByHeightWeight:
    def __call__(self, heights: List[int], weights: List[int]):
        students = [(height, weight, i) for i, (height, weight) in enumerate(zip(heights, weights), start=1)]
        students.sort()
        return list(map(lambda x: x[-1], students))

4. 报数问题

4.1. 题目描述

有n个人围成一圈,顺序排号为1-n。

从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。

4.2. 输入描述

输入人数n(n < 1000)

4.3. 输出描述

输出最后留下的是原来第几号

4.4. 用例

在这里插入图片描述

4.5. 题目解析

本题是经典的约瑟夫环问题,最佳解题策略是利用循环链表。

因此,本题的关键是实现循环链表。
简易的循环链表实现:

  • 循环链表节点定义
    节点双向性prev、next(方便节点删除)
    节点值val

  • 循环链表的属性:
    链表长度size
    链表头节点head
    链表尾节点tail

  • 循环链表的操作
    尾增节点(append操作)
    删除任意节点(remove操作)

  • 循环链表尾增节点,需要注意:
    如果size>0,则相当于只需要更新循环链表的尾节点tail
    如果size == 0,则相当于更新循环链表的head和tail

  • 循环链表删除任意节点,需要注意:
    如果删除的不是head,tail节点,则只需要将被删除节点的prev和next节点关联
    如果删除的是head或tail,则还需要更新head、tail指向

4.6. 代码

class Node:
    def __init__(self, val: int):
        self.id = val
        self.next = None
        self.prev = None


class CycleLinkedList:
    def __init__(self):
        self.size = 0
        self.head = None
        self.tail = None

    def append(self, node: int):
        node = Node(node)

        if self.size == 0:
            self.head = node
            self.tail = node

        else:
            self.tail.next = node
            node.prev = self.tail
            self.tail = node

        self.tail.next = self.head
        self.head.prev = self.tail
        self.size += 1

    def remove(self, node: Node):
        prev, next = node.prev, node.next
        prev.next = next
        next.prev = prev

        node.prev = node.next = None

        if self.head == node:
            self.head = next
        if self.tail == node:
            self.tail = prev

        self.size -= 1
        return next


class Remove3:
    def __call__(self, n):
        circle = CycleLinkedList()
        for i in range(n):
            if (i + 1) % 3 == 0:
                continue
            circle.append(i + 1)

        cnt = 0
        node = circle.head
        while circle.size > 1:
            cnt += 1
            if cnt == 3:
                node = circle.remove(node)
                cnt = 0
            else:
                node = node.next
        return node.id
  • 29
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值