[英雄星球六月集训LeetCode解题日报] 第17日 宽搜

日报

  • 今天出去忙了一天,晚上回来再开始补作业。
  • 还好题目不是很难。
  • 每日一题也是easy。

题目

一、 2059. 转化数字的最小运算数

链接: 2059. 转化数字的最小运算数

1. 题目描述

给你一个下标从 0 开始的整数数组 nums ,该数组由 互不相同 的数字组成。另给你两个整数 start 和 goal 。

整数 x 的值最开始设为 start ,你打算执行一些运算使 x 转化为 goal 。你可以对数字 x 重复执行下述运算:

如果 0 <= x <= 1000 ,那么,对于数组中的任一下标 i(0 <= i < nums.length),可以将 x 设为下述任一值:

x + nums[i]
x - nums[i]
x ^ nums[i](按位异或 XOR)
注意,你可以按任意顺序使用每个 nums[i] 任意次。使 x 越过 0 <= x <= 1000 范围的运算同样可以生效,但该该运算执行后将不能执行其他运算。

返回将 x = start 转化为 goal 的最小操作数;如果无法完成转化,则返回 -1

2. 思路分析

没什么好思路,就层先暴搜吧~

  • 每一步操作数是3,按理说应该封一下数组,但是我困了,就在搜索里边复制三遍代码吧~
  • 起始状态start,目标goal,题目要求中间步不能超范围,但goal可以,那么在状态监测入队之前判断goal即可。
  • 用层先先法,记录step,就可以不用给每个状态记步数啦。
  • 就还挺快。
  • 在这里插入图片描述
3. 代码实现
class Solution:
    def minimumOperations(self, nums: List[int], start: int, goal: int) -> int:
        step = 0
        q = deque([start])
        visited = {start}
        while q:
            step += 1
            new_q = deque()
            while q:
                cur = q.popleft()
                for num in nums:
                    nxt = cur - num
                    if nxt == goal:
                        return step
                    if 0<=nxt<=1000 and nxt not in visited:
                        new_q.append(nxt)
                        visited.add(nxt)
                    nxt = cur + num
                    if nxt == goal:
                        return step
                    if 0<=nxt<=1000 and nxt not in visited:
                        new_q.append(nxt)
                        visited.add(nxt)
                    nxt = cur ^ num
                    if nxt == goal:
                        return step
                    if 0<=nxt<=1000 and nxt not in visited:
                        new_q.append(nxt)
                        visited.add(nxt)
            q = new_q
        return -1

二、 690. 员工的重要性

链接: 690. 员工的重要性

1. 题目描述

给定一个保存员工信息的数据结构,它包含了员工 唯一的 id ,重要度 和 直系下属的 id 。

比如,员工 1 是员工 2 的领导,员工 2 是员工 3 的领导。他们相应的重要度为 15 , 10 , 5 。那么员工 1 的数据结构是 [1, 15, [2]] ,员工 2的 数据结构是 [2, 10, [3]] ,员工 3 的数据结构是 [3, 5, []] 。注意虽然员工 3 也是员工 1 的一个下属,但是由于 并不是直系 下属,因此没有体现在员工 1 的数据结构中。

现在输入一个公司的所有员工信息,以及单个员工 id ,返回这个员工和他所有下属的重要度之和。

2. 思路分析

这不就是个n叉树求某颗子树的权和么。懒得建树,用哈希表模拟关系建图dfs完事。
在这里插入图片描述

3. 代码实现
class Solution:
    def getImportance(self, employees: List['Employee'], id: int) -> int:
        # dfs暴搜
        important = {e.id:e.importance for e in employees}
        leadwho = {e.id:e.subordinates for e in employees}
        def dfs(i):
            ret = important[i]
            if leadwho[i]:
                ret += sum(dfs(j) for j in leadwho[i])
            return ret
        return dfs(id)

三、 672. 灯泡开关 Ⅱ

链接: 672. 灯泡开关 Ⅱ

1. 题目描述

现有一个房间,墙上挂有 n 只已经打开的灯泡和 4 个按钮。在进行了 m 次未知操作后,你需要返回这 n 只灯泡可能有多少种不同的状态。

假设这 n 只灯泡被编号为 [1, 2, 3 …, n],这 4 个按钮的功能如下:

  1. 将所有灯泡的状态反转(即开变为关,关变为开)
  2. 将编号为偶数的灯泡的状态反转
  3. 将编号为奇数的灯泡的状态反转
  4. 将编号为 3k+1 的灯泡的状态反转(k = 0, 1, 2, …)
2. 思路分析

先找规律:

  • 发现本题循环节是6,所以n可以min(n,6)
  • 操作就是异或,预处理一下每次的操作,共四种。
  • 初始状态全1(全亮)
  • 然后层先暴搜m次。
  • 这里因为是求不同状态数,因此可以用set当q,不过我顺手用了q,反正层先也得再开个集合,就顺手用了。
  • m次后len(q)就是答案。
3. 代码实现
class Solution:
    def flipLights(self, n: int, presses: int) -> int:
        """
        本题循环节是6,n可以状压6位二进制当状态。
        每种操作,执行两次等于没执行,因此m其实也可以压缩,不过我有点困先不琢磨了
        """
        ans = set()
        n = min(n,6)
        odd=even=k31=0
        for i in range(n):
            if i&1 == 0:
                odd |= 1<<i 
            if i&1 == 1:
                even |= 1<<i 
            if i%3 == 0:
                k31 |= 1<<i 
        operate = [odd,even,k31,(1<<n)-1]
        cur = (1<<n) - 1
        # print(n,cur,operate)
            
        q = deque([cur])
        for i in range(presses):
            cur_set = set()
            while q:
                cur = q.popleft()
                for op in operate:
                    nxt = cur^op
                    cur_set.add(nxt)
                    # print(cur,op,cur_set)
            q = deque(cur_set)
        return len(q)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值