OPPO 后端二面,凉凉。。。

news2025/2/27 4:38:56

美众议院通过 TikTok 法案

之前我们讲了 老美要求字节跳动在 165 天内剥离短视频应用 TikTok,当时的最新进度是 TikTok 给 1.7 亿美国用户发弹窗,发动用户群众给国会打电话进行抗议。

但显然这点力度的抗议并不会造成什么实质影响。

昨晚,美国众议院的议员们正式投票通过了该法案(H.R.7521),之后的流程还需要得到美国参议院的通过,然后才是提交给总统拜登批准。

美国众议院的威斯康星州共和党众议员迈克·加拉格尔(右)是一项针对TikTok法案的主要支持者之一
美国众议院的威斯康星州共和党众议员迈克·加拉格尔(右)是一项针对TikTok法案的主要支持者之一

看似流程还长,但大概率不会出现什么变数,毕竟针对 TikTok 是两党的少数共识。

在正式投票之前,白宫秘书就公开称赞该提案,称拜登政府"希望看到这项法案得以通过,这样它就能被送到总统的办公桌上"。

这事儿如果真的被美国得逞,真的是很坏的示范。

现在比较合理的破局方式,只能是期望当时躲过特朗普狙击的方法能再奏效一次。

希望会有一些线下的抗议活动,动静越大越好,尽量拖延法案通过的日期。

只要法案通过日期延后,再加上法案生效后还有 165 天时间,就有可能避开美国大选,到时如果发生新政交接,或许就能再次获得喘息机会。

...

回归主线。

真心希望 TikTok 不会原地变外企,先不做字节跳动相关题目了。

来看一道 OPPO 二面算法原题。

蓝厂的花边新闻虽然不多,但一直是低调赚大钱的代表之一。

这次二面出的算法题水平也不错。

相比原题,题面稍有修改,但数据范围和解法完全一致。

题目描述

平台:LeetCode

题号:864

给定一个二维网格 g,其中:

  • '.' 代表一个空房间
  • '#' 代表一堵墙
  • '@' 是起点
  • 小写字母代表钥匙
  • 大写字母代表锁

我们从起点开始出发,一次移动是指向四个基本方向之一行走一个单位空间。

我们不能在网格外面行走,也无法穿过一堵墙。

如果途经一个钥匙,我们就把它捡起来,除非我们手里有对应的钥匙,否则无法通过锁。

假设 k 为 钥匙/锁 的个数,且满足  ,字母表中的前 k 个字母在网格中都有自己对应的一个小写和一个大写字母。

换言之,每个锁有唯一对应的钥匙,每个钥匙也有唯一对应的锁。另外,代表钥匙和锁的字母互为大小写并按字母顺序排列。

返回获取所有钥匙所需要的移动的最少次数。

如果无法获取所有钥匙,返回 -1 。

示例 1: alt

输入:g = ["@.a.#","###.#","b.A.B"]

输出:8

解释:目标是获得所有钥匙,而不是打开所有锁。

示例 2: alt

输入:g = ["@..aA","..B#.","....b"]

输出:6

示例 3: alt

输入: g = ["@Aa"]

输出: -1

提示:

  • g[i][j] 只含有  '.', '#''@''a'-'f' 以及  'A'-'F'
  • 钥匙的数目范围是 
  • 每个钥匙都对应一个不同的字母
  • 每个钥匙正好打开一个对应的锁

BFS + 状态压缩

一道常规的 BFS 运用题,只不过需要在 BFS 过程中记录收集到的钥匙状态。

利用「钥匙数量不超过 ,并按字母顺序排列」,我们可以使用一个 int 类型二进制数 state 来代指当前收集到钥匙情况:

  • state 的二进制中的第 位为 1,代表当前种类编号为 的钥匙 「已被收集」,后续移动若遇到对应的锁则 「能通过」
  • state 的二进制中的第 位为 0,代表当前种类编号为 的钥匙 「未被收集」,后续移动若遇到对应的锁则 「无法通过」

其中「钥匙种类编号」则按照小写字母先后顺序,从 开始进行划分对应:即字符为 a 的钥匙编号为 0,字符为 b 的钥匙编号为 1,字符为 c 的钥匙编号为 2 ...

当使用了这样的「状态压缩」技巧后,我们可以很方便通过「位运算」进行 「钥匙检测」「更新钥匙收集状态」

  • 钥匙检测: (state >> k) & 1,若返回 1 说明第 位为 1,当前持有种类编号为 k 的钥匙
  • 更新钥匙收集状态: state |= 1 << k,将 state 的第 位设置为 1,代表当前新收集到种类编号为 k 的钥匙

搞明白如何记录当前收集到的钥匙状态后,剩下的则是常规 BFS 过程:

  1. 起始遍历一次棋盘,找到起点位置,并将其进行入队,队列维护的是 三元组状态(其中 代表当前所在的棋盘位置, 代表当前的钥匙收集情况) 同时统计整个棋盘所包含的钥匙数量 cnt,并使用 数组/哈希表 记录到达每个状态所需要消耗的最小步数 step

  2. 进行四联通方向的 BFS,转移过程中需要注意「遇到锁时,必须有对应钥匙才能通过」&「遇到钥匙时,需要更新对应的 state 再进行入队」

  3. BFS 过程中遇到 state = (1 << cnt) - 1 时,代表所有钥匙均被收集完成,可结束搜索

Java 代码:

class Solution {
    static int N = 35, K = 10, INF = 0x3f3f3f3f;
    static int[][][] dist = new int[N][N][1 << K];
    static int[][] dirs = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
    public int shortestPathAllKeys(String[] g) {
        int n = g.length, m = g[0].length(), cnt = 0;
        Deque<int[]> d = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                Arrays.fill(dist[i][j], INF);
                char c = g[i].charAt(j);
                if (c == '@') {
                    d.addLast(new int[]{i, j, 0});
                    dist[i][j][0] = 0;
                } else if (c >= 'a' && c <= 'z') cnt++;
            }
        }
        while (!d.isEmpty()) {
            int[] info = d.pollFirst();
            int x = info[0], y = info[1], cur = info[2], step = dist[x][y][cur];
            for (int[] di : dirs) {
                int nx = x + di[0], ny = y + di[1];
                if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
                char c = g[nx].charAt(ny);
                if (c == '#'continue;
                if ((c >= 'A' && c <= 'Z') && (cur >> (c - 'A') & 1) == 0continue;
                int ncur = cur;
                if (c >= 'a' && c <= 'z') ncur |= 1 << (c - 'a');
                if (ncur == (1 << cnt) - 1return step + 1;
                if (step + 1 >= dist[nx][ny][ncur]) continue;
                dist[nx][ny][ncur] = step + 1;
                d.addLast(new int[]{nx, ny, ncur});
            }
        }
        return -1;
    }
}

C++ 代码:

class Solution {
    int N = 35, K = 10, INF = 0x3f3f3f3f;
    vector<vector<vector<int>>> dist = vector<vector<vector<int>>>(N, vector<vector<int>>(N, vector<int>(1<<K, INF)));
    vector<vector<int>> dirs = {{1,0}, {-1,0}, {0,1}, {0,-1}};
public:
    int shortestPathAllKeys(vector<string>& g) {
        int n = g.size(), m = g[0].size(), cnt = 0;
        queue<vector<int>> d;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                fill(dist[i][j].begin(), dist[i][j].end(), INF);
                char c = g[i][j];
                if (c == '@') {
                    d.push({i, j, 0});
                    dist[i][j][0] = 0;
                } else if (c >= 'a' && c <= 'z') cnt++;
            }
        }
        while (!d.empty()) {
            vector<int> info = d.front();
            d.pop();
            int x = info[0], y = info[1], cur = info[2], step = dist[x][y][cur];
            for (vector<int> di : dirs) {
                int nx = x + di[0], ny = y + di[1];
                if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
                char c = g[nx][ny];
                if (c == '#'continue;
                if ((c >= 'A' && c <= 'Z') && (cur >> (c - 'A') & 1) == 0continue;
                int ncur = cur;
                if (c >= 'a' && c <= 'z') ncur |= 1 << (c - 'a');
                if (ncur == (1 << cnt) - 1return step + 1;
                if (step + 1 >= dist[nx][ny][ncur]) continue;
                dist[nx][ny][ncur] = step + 1;
                d.push({nx, ny, ncur});
            }
        }
        return -1;
    }
};

Python3 代码:

class Solution:
    def shortestPathAllKeys(self, g: List[str]) -> int:
        dirs = [[0,1], [0,-1], [1,0], [-1,0]]
        n, m, cnt = len(g), len(g[0]), 0
        dist = defaultdict(lambda : 0x3f3f3f3f)
        for i in range(n):
            for j in range(m):
                c = g[i][j]
                if c == '@':
                    d = deque([(i, j, 0)])
                    dist[(i, j, 0)] = 0
                elif 'a' <= c <= 'z':
                    cnt += 1
        while d:
            x, y, cur = d.popleft()
            step = dist[(x, y, cur)]
            for di in dirs:
                nx, ny = x + di[0], y + di[1]
                if nx < 0 or nx >= n or ny < 0 or ny >= m:
                    continue
                c = g[nx][ny]
                if c == '#':
                    continue
                if 'A' <= c <= 'Z' and (cur >> (ord(c) - ord('A')) & 1) == 0:
                    continue
                ncur = cur
                if 'a' <= c <= 'z':
                    ncur |= (1 << (ord(c) - ord('a')))
                if ncur == (1 << cnt) - 1:
                    return step + 1
                if step + 1 >= dist[(nx, ny, ncur)]:
                    continue
                dist[(nx, ny, ncur)] = step + 1
                d.append((nx, ny, ncur))
        return -1

TypeScript 代码:

function shortestPathAllKeys(g: string[]): number {
    const dirs = [[1,0],[-1,0],[0,1],[0,-1]]
    let n = g.length, m = g[0].length, cnt = 0
    const dist = new Array<Array<Array<number>>>()
    for (let i = 0; i < n; i++) {
        dist[i] = new Array<Array<number>>(m)
        for (let j = 0; j < m; j++) {
            dist[i][j] = new Array<number>(1 << 10).fill(0x3f3f3f3f)
        }
    }
    const d = []
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < m; j++) {
            if (g[i][j] == '@') {
                d.push([i, j, 0]); dist[i][j][0] = 0
            } else if (g[i][j] >= 'a' && g[i][j] <= 'z') cnt++
        }
    }
    while (d.length > 0) {
        const info = d.shift()
        const x = info[0], y = info[1], cur = info[2], step = dist[x][y][cur]
        for (const di of dirs) {
            const nx = x + di[0], ny = y + di[1]
            if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue
            const c = g[nx][ny]
            if (c == '#'continue
            if ('A' <= c && c <= 'Z' && ((cur >> (c.charCodeAt(0) - 'A'.charCodeAt(0)) & 1) == 0)) continue
            let ncur = cur
            if ('a' <= c && c <= 'z') ncur |= 1 << (c.charCodeAt(0) - 'a'.charCodeAt(0))
            if (ncur == (1 << cnt) - 1return step + 1
            if (step + 1 >= dist[nx][ny][ncur]) continue
            d.push([nx, ny, ncur])
            dist[nx][ny][ncur] = step + 1
        }
    }
    return -1
}
  • 时间复杂度:
  • 空间复杂度:

我是宫水三叶,每天都会分享算法知识,并和大家聊聊近期的所见所闻。

欢迎关注,明天见。

更多更全更热门的「笔试/面试」相关资料可访问排版精美的 合集新基地 🎉🎉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1528570.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

门店运营三大核心揭秘:打造高效盈利模式的关键

在当今竞争激烈的商业环境中&#xff0c;开设一家成功的实体店并非易事。对于那些渴望投身实体店创业或已经在创业道路上的人来说&#xff0c;了解如何打造高效盈利模式是至关重要的。作为一名经营鲜奶吧5年时间的创业者&#xff0c;我将持续在网上分享开店的干货和见解&#x…

MySQL最实用面试题(2024-3-14持续更新中)

MySQL篇面试题 一、介绍 ​ 这是由小龙同学自己总结领悟的mysql面试题的解析&#xff0c;也是面试宝典 二、题目 1.数据库三大范式&#xff1a; –作用&#xff1a; ​ 使表结构清晰&#xff0c;减少数据冗余&#xff08;简单讲就是重复&#xff09;&#xff0c;提高查询…

Kafka:分布式消息队列

1. 简介 介绍 Kafka 的概述、优势和劣势&#xff0c;以及应用场景。 2. 基本概念 2.1 架构 一个典型的 Kafka 体系架构包括若干 Producer、若干Broker、若干 Consumer&#xff0c;以及一个ZooKeeper集群。 ZooKeeper是Kafka用来负责集群元数据的管理、控制器的选举等操作的…

基于Spring Boot的社区便民服务管理系统的设计与实现

摘 要 二十一世纪我们的社会进入了信息时代&#xff0c;信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针对这一…

js逆向-某东cfe滑块逆向分析

声明 本文仅供学习参考&#xff0c;如有侵权可私信本人删除&#xff0c;请勿用于其他途径&#xff0c;违者后果自负&#xff01; 如果觉得文章对你有所帮助&#xff0c;可以给博主点击关注和收藏哦&#xff01; 分析 网址&#xff1a; aHR0cHM6Ly9jZmUubS5qZC5jb20vcHJpdmF…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Panel)

可滑动面板&#xff0c;提供一种轻量的内容展示窗口&#xff0c;方便在不同尺寸中切换。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 可以包含子组件。 说明&#xff1a; 子组件类型&a…

最常见的软件测试面试题及答案

随着企业对于软件质量的重视&#xff0c;软件测试工程师倍受青睐&#xff0c;对于求职者的要求也在提高&#xff0c;不仅要求求职者具备扎实的理论功底&#xff0c;还要有丰富的实战经验&#xff0c;这就给软件测试工程师求职增加了难度。今天千锋老师就给大家分享一些常见的软…

二维码怎么转链接使用?在线分解二维码的操作技巧

随着二维码应用的不断增多&#xff0c;很多内容都通过扫码的方式来展现。在遇到部分特殊情况下&#xff0c;无法通过扫码的方式展现内容时&#xff0c;就需要将二维码分解成链接后&#xff0c;通过点击链接的方法来访问内容。那么二维码解码的方法及步骤是什么样的呢&#xff1…

【论文阅读】(DALL-E)Zero-Shot Text-to-Image Generation

&#xff08;DALL-E&#xff09;Zero-Shot Text-to-Image Generation 引用&#xff1a; Ramesh A, Pavlov M, Goh G, et al. Zero-shot text-to-image generation[C]//International conference on machine learning. Pmlr, 2021: 8821-8831. 论文链接&#xff1a; [2102.120…

基于Spring Boot框架的文学名著分享系统的设计与实现

摘 要 随着世界经济信息化、全球化的到来和互联网的飞速发展&#xff0c;推动了各行业的改革。若想达到安全&#xff0c;快捷的目的&#xff0c;就需要拥有信息化的组织和管理模式&#xff0c;建立一套合理、动态的、交互友好的、高效的文学名著分享系统。当前的信息管理存在工…

渲染农场:怎么提高设计效率与质量?

作为设计师&#xff0c;在各行业中我们经常需要渲染出效果图来展示我们的设计作品。当设计项目需要大量的效果图来展示产品时&#xff0c;如何能够利用渲染农场来提高渲图的效率呢&#xff1f; 渲染农场一般就是指&#xff1a;云渲染农场&#xff0c;利用云计算和高性能服务器来…

MySQL数据导入的方式介绍

MySQL数据库中的数据导入是一个常见操作&#xff0c;它涉及将数据从外部源转移到MySQL数据库表中。在本教程中&#xff0c;我们将探讨几种常见的数据导入方式&#xff0c;包括它们的特点、使用场景以及简单的示例。 1. 命令行导入 使用MySQL命令行工具mysql是导入数据的…

ASP .Net Core 8.0 依赖注入的三种注入模式

&#x1f433;前言 &#x1f340;在.NET中&#xff0c;依赖注入&#xff08;Dependency Injection&#xff0c;简称DI&#xff09;是一种设计模式&#xff0c;用于解耦组件之间的依赖关系。 依赖注入的核心思想是将对象的依赖关系&#xff08;即对象所需的其他服务或组件&#…

如何确保OKR既具有挑战性又实际可行?

在目标管理的世界里&#xff0c;OKR&#xff08;Objectives and Key Results&#xff09;作为一种高效的目标设定和跟踪工具&#xff0c;已经越来越受到企业的青睐。然而&#xff0c;制定既具有挑战性又实际可行的OKR并非易事。本文将探讨如何确保OKR既具有挑战性又实际可行&am…

Kubernetes 项目整体布局 el-container

整体布局整体布局 你可能会去敲不同的项目&#xff0c;有很多种平台。那么其实都是可以复用的。唯一不同的就是main里面的内容是不同的&#xff0c;边框架子都是相同的。其实框架是不怎么变化的&#xff0c;变化的是main里面。 src/layout/Layout.vue 这里需要新增一个页面Lay…

Gitlab部署及使用

1. 简介 GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用 Git 作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务。Gitlab是目前被广泛使用的基于 git 的开源代码管理平台&#xff0c;基于Ruby on Rails构建&#xff0c;主要针对软件开发过程中产生的代码…

抖音视频批量提取软件|无水印视频下载

抖音视频批量提取软件&#xff0c;让您高效下载精彩内容&#xff01; 您是否经常需要下载抖音视频&#xff0c;但传统的下载方式繁琐且低效&#xff1f;别担心&#xff0c;我们为您提供了一款强大而智能的抖音视频批量提取软件&#xff0c;让您轻松实现下载无水印的精彩内容&am…

怎么制作电子版报纸

​随着科技的飞速发展&#xff0c;电子版报纸已成为信息传播的重要渠道。它不仅方便快捷&#xff0c;而且环保节能&#xff0c;深受读者喜爱。如何制作电子版报纸&#xff0c;让您轻松掌握这一技能呢&#xff1f; 1.打开FLBOOK电子杂志制作网站 2.点击模板&#xff0c;FLBOOK有…

塑料工厂5G智能制造数字孪生可视化平台,推进塑料行业数字化转型

塑料工厂5G智能制造数字孪生可视化平台&#xff0c;推进塑料行业数字化转型。塑料制造行业作为重要的工业领域&#xff0c;亟需借助这一平台实现产业升级与转型&#xff0c;以适应市场的变化和提高生产效率。传统的塑料制造过程往往存在生产效率低下、资源浪费、环境污染等问题…

为什么技术人员副业赚钱那么难?

公众号&#xff1a;小北技术圈。 34岁老程序员&#xff0c;长期探索副业项目&#xff0c;写过IDEA插件&#xff0c;搞过工具导航&#xff0c;做过出海网站&#xff0c;运营过自媒体。欢迎提前探索35岁程序员的第二赛道。 每周分享干货内容。寻找100个技术人员&#xff0c;聚在…