抖音 UG 社招一面算法原题

史上最严热点新机制

或许是受到前段时间「巴黎丢作业」的影响,抖音近日(5月27日)实施了新的热点内容核实机制。

具体来说,若用户在抖音以热点事件当事人身份发声,抖音将联系当事人进行身份认证。

逾期未认证的用户,抖音将采取包括强提醒标注、禁言等一系列措施,直至用户提供可信材料。

同时,对于演绎类内容,抖音要求发布者必须显著标注"虚构演绎"声明,对于部分疑似摆拍的热点内容,抖音称将主动请求各地相关部门核实或联动各地新闻机构调查。

如此一来,基本上是把"造谣骗流量"的车门焊死了,但这也将大大增加抖音方面的运营成本。

个人感觉:初心很好,但如果严格按照上述说的来做,其实很难达到好的效果。

从以前的「纯算法」到现在的「人工介入」,以及认证材料的合理性,再到标记的及时性,都可能会让内容平台呈现的效果大打折扣。

要知道,一个视频如果因为新规则晚了半天进入流量池,可能就已经错过了最佳传播时间了。

而且任何打击类的新规则,也都无法避免的误伤问题。

对于抖音提出的「史上最严热点新机制」,你怎么看?

...

回归主题。

来一道和「字节跳动」相关的题目。

题目描述

平台:LeetCode

题号:907

给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。

由于答案可能很大,因此 返回答案模

示例 1:

输入:arr = [3,1,2,4]

输出:17

解释:
子数组为 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]。 
最小值为 3,1,2,4,1,1,2,1,1,1,和为 17。

示例 2:

输入:arr = [11,81,94,43,3]

输出:444

提示:

单调栈 + 数学

原问题为求所有子数组的最小值之和。

统计所有子数组需要枚举左右端点,复杂度为 ,对于每个子数组,我们还需要通过线性扫描的方式找到其最小值,复杂度为 ,因此朴素解法的整体复杂度为 ,题目给定数据范围为 ,会 TLE

由于我们是从子数组中取最小值来进行累加,即参与答案构成的每个数必然某个具体的

「因此我们可以将原问题转化为「考虑统计每个 对答案的贡献」。」

对于某一个 而言,我们考虑其能够作为哪些子数组的最小值。

我们可以想象以 为中心,分别往两端进行拓展,只要新拓展的边界不会改变「 为当前子数组的最小值」的性质即可。

换句话说,我们需要找到 作为最小值的最远左右边界,即找到 左右最近一个比其小的位置 lr

「在给定序列中,找到任意 最近一个比其大/小的位置,可使用「单调栈」进行求解。」

到这里,我们会自然想到,通过单调栈的方式,分别预处理除 lr 数组:

  • l[i] = loc 含义为下标 i 左边最近一个比 arr[i] 小的位置是 loc(若在 左侧不存在比其小的数,则 loc = -1
  • r[i] = loc 含义为下标 i 右边最近一个比 arr[i] 小的位置是 loc(若在 左侧不存在比其小的数,则 loc = n

当我们预处理两数组后,通过简单「乘法原理」即可统计以 为最小值时,子数组的个数:

  • 包含 的子数组左端点个数为
  • 包含 的子数组右端点个数为

子数组的个数 X 子数组最小值 ,即是当前 对答案的贡献:

「统计所有 对答案的贡献即是最终答案,但我们忽略了「当 arr 存在重复元素,且该元素作为子数组最小值时,最远左右端点的边界越过重复元素时,导致重复统计子数组」的问题。」

我们不失一般性的举个 🌰 来理解(下图):

alt

为了消除这种重复统计,我们可以将「最远左右边界」的一端,从「严格小于」调整为「小于等于」,从而实现半开半闭的效果。

Java 代码:

class Solution {
    int MOD = (int)1e9+7;
    public int sumSubarrayMins(int[] arr) {
        int n = arr.length, ans = 0;
        int[] l = new int[n], r = new int[n];
        Arrays.fill(l, -1); Arrays.fill(r, n);
        Deque<Integer> d = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            while (!d.isEmpty() && arr[d.peekLast()] >= arr[i]) r[d.pollLast()] = i;
            d.addLast(i);
        }
        d.clear();
        for (int i = n - 1; i >= 0; i--) {
            while (!d.isEmpty() && arr[d.peekLast()] > arr[i]) l[d.pollLast()] = i;
            d.addLast(i);
        }
        for (int i = 0; i < n; i++) {
            int a = i - l[i], b = r[i] - i;
            ans += a * 1L * b % MOD * arr[i] % MOD;
            ans %= MOD;
        }
        return ans;
    }
}

C++ 代码:

class Solution {
public:
    int MOD = 1e9 + 7;
    int sumSubarrayMins(vector<int>& arr) {
        int n = arr.size(), ans = 0;
        vector<intl(n, -1)r(n, n);
        stack<int> d;
        for (int i = 0; i < n; i++) {
            while (!d.empty() && arr[d.top()] >= arr[i]) {
                r[d.top()] = i;
                d.pop();
            }
            d.push(i);
        }
        while (!d.empty()) d.pop();
        for (int i = n - 1; i >= 0; i--) {
            while (!d.empty() && arr[d.top()] > arr[i]) {
                l[d.top()] = i;
                d.pop();
            }
            d.push(i);
        }
        for (int i = 0; i < n; i++) {
            long long a = i - l[i], b = r[i] - i;
            ans = (ans + a * b % MOD * arr[i] % MOD) % MOD;
        }
        return ans;
    }
};

Python 代码:

class Solution:
    def sumSubarrayMins(self, arr: List[int]) -> int:
        n, ans = len(arr), 0
        l, r = [-1] * n, [n] * n
        stk = []
        for i in range(n):
            while stk and arr[stk[-1]] >= arr[i]:
                r[stk.pop()] = i
            stk.append(i)
        stk = []
        for i in range(n - 1-1-1):
            while stk and arr[stk[-1]] > arr[i]:
                l[stk.pop()] = i
            stk.append(i)
        for i in range(n):
            a, b = i - l[i], r[i] - i
            ans += a * b * arr[i]
        return ans % (10 ** 9 + 7)

TypeScript 代码:

const MOD = 1000000007
function sumSubarrayMins(arr: number[]): number {
    let n = arr.length, ans = 0
    const l = new Array<number>(n).fill(-1), r = new Array<number>(n).fill(n)
    const stk = new Array<number>(n).fill(0)
    let he = 0, ta = 0
    for (let i = 0; i < n; i++) {
        while (he < ta && arr[stk[ta - 1]] >= arr[i]) r[stk[--ta]] = i
        stk[ta++] = i
    }
    he = ta = 0
    for (let i = n - 1; i >= 0; i--) {
        while (he < ta && arr[stk[ta - 1]] > arr[i]) l[stk[--ta]] = i
        stk[ta++] = i
    }
    for (let i = 0; i < n; i++) {
        const a = i - l[i], b = r[i] - i
        ans += a * b % MOD * arr[i] % MOD
        ans %= MOD
    }
    return ans
}
  • 时间复杂度:
  • 空间复杂度:

优化

实际上,当我们从栈中弹出某个 时,其右边界必然是导致其弹出的 arr[r](当前所遍历到的元素),而 若存在左边界,必然是位于 栈中的前一位置,即 弹出后的新栈顶元素(若不存在物理左边界,则左边界为 )。

Java 代码:

class Solution {
    int MOD = (int)1e9+7;
    public int sumSubarrayMins(int[] arr) {
        int n = arr.length, ans = 0;
        Deque<Integer> d = new ArrayDeque<>();
        for (int r = 0; r <= n; r++) {
            int t = r < n ? arr[r] : 0;
            while (!d.isEmpty() && arr[d.peekLast()] >= t) {
                int cur = d.pollLast();
                int l = d.isEmpty() ? -1 : d.peekLast();
                int a = cur - l, b = r - cur;
                ans += a * 1L * b % MOD * arr[cur] % MOD;
                ans %= MOD;
            }
            d.addLast(r);
        }
        return ans;
    }
}

C++ 代码:

class Solution {
public:
    int MOD = 1e9 + 7;
    int sumSubarrayMins(vector<int>& arr) {
        int n = arr.size(), ans = 0;
        deque<int> d;
        for (int r = 0; r <= n; r++) {
            int t = (r < n) ? arr[r] : 0;
            while (!d.empty() && arr[d.back()] >= t) {
                int cur = d.back();
                d.pop_back();
                int l = d.empty() ? -1 : d.back();
                long long a = cur - l, b = r - cur;
                ans = (ans + a * b % MOD * arr[cur] % MOD) % MOD;
            }
            d.push_back(r);
        }
        return ans;
    }
};

Python 代码:

class Solution:
    def sumSubarrayMins(self, arr: List[int]) -> int:
        n, ans = len(arr), 0
        stk = []
        for r in range(n + 1):
            t = arr[r] if r < n else 0
            while stk and arr[stk[-1]] >= t:
                cur = stk.pop()
                l = stk[-1if stk else -1
                a, b = cur - l, r - cur
                ans += a * b * arr[cur]
            stk.append(r)
        return ans % (10 ** 9 + 7)

TypeScript 代码:

const MOD = 1000000007
function sumSubarrayMins(arr: number[]): number {
    let n = arr.length, ans = 0
    const stk = new Array<number>(n).fill(0)
    let he = 0, ta = 0
    for (let r = 0; r <= n; r++) {
        const t = r < n ? arr[r] : 0
        while (he < ta && arr[stk[ta - 1]] >= t) {
            const cur = stk[--ta]
            const l = he < ta ? stk[ta - 1] : -1
            const a = cur - l, b = r - cur
            ans += a * b % MOD * arr[cur] % MOD
            ans %= MOD
        }
        stk[ta++] = r
    }
    return ans
}
  • 时间复杂度:
  • 空间复杂度:

最后

给大伙通知一下 📢 :

全网最低价 LeetCode 会员目前仍可用 ~

📅 年度会员:有效期加赠两个月!!; 季度会员:有效期加赠两周!!

🧧 年度会员:获 66.66 现金红包!!; 季度会员:获 22.22 现金红包!!

🎁 年度会员:参与当月丰厚专属实物抽奖(中奖率 > 30%)!!

专属链接:leetcode.cn/premium/?promoChannel=acoier

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

欢迎关注,明天见。

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

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

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

相关文章

Flutter开发效率提升1000%,Flutter Quick教程之在特定位置插入Widget

当我们要将Widget插入一个Column,Row或者Listview等有多个子元素的Widget的时候&#xff0c;有两种情况&#xff0c;一种是顺序插入&#xff0c;一种是非顺序插入。顺序插入就是Widget的排列顺序和插入顺序相同&#xff0c;非顺序插入则不是。 一&#xff0c;顺序插入。如图所…

Vue进阶之Vue无代码可视化项目(三)

Vue无代码可视化项目 项目初始化store的使用DataSourceView.vuestores/counter.ts开发模式按钮store/editor.tsLayoutView.vue导航条安装图标iconpackage.jsonstore/debug.tssrc/components/AppNavigator.vueAppNavigator.ts:AppNavigator.vue:theme样式theme/reset.csstheme/v…

重庆耶非凡科技有限公司的选品师项目加盟靠谱吗?

在当今电子商务的浪潮中&#xff0c;选品师的角色愈发重要。而重庆耶非凡科技有限公司以其独特的选品师项目&#xff0c;在行业内引起了广泛关注。对于想要加盟该项目的人来说&#xff0c;项目的靠谱性无疑是首要考虑的问题。 首先&#xff0c;我们来看看耶非凡科技有限公司的背…

【SpringMVC】_设置响应状态码与Header

目录 1. 设置响应状态码 2. 设置响应Header 2.1 设置Content-Type 2.1.1 不使用RequestMapping的produce属性 2.1.2 使用RequestMapping的produce属性 2.2 设置/新增其他Header 1. 设置响应状态码 Spring是基于servlet实现的&#xff0c;设置HTTP响应的状态码可以通过se…

521源码-源码下载-WordPress报错:Allowed memory size of 134217728 bytes exhausted错误解决方法

在wordpress中使用站内搜索或者打开一个页面时提示错误&#xff1a; Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) 致命错误:允许耗尽内存大小为134217728字节(试图分配20480字节) 分析&#xff1a;经过检查发现&#x…

【Ubuntu】【Shell】执行sh脚本报错“xxx.sh:/bin/bash^M:解释器错误: 没有那个文件或目录“

背景 在自己Ubuntu环境执行sh脚本&#xff0c;报错"xxx.sh&#xff1a;/bin/bash^M&#xff1a;解释器错误: 没有那个文件或目录"&#xff0c;查了下是Ubuntu系统默认的shell是dash: 修改配置过下&#xff0c;变成bash 解决方案 在终端执行&#xff1a; sudo dp…

YOLOv8 深度详解!一文看懂,快速上手

YOLOv8 深度详解&#xff01;一文看懂&#xff0c;快速上手 原文&#xff1a;YOLOv8 深度详解&#xff01;一文看懂&#xff0c;快速上手 - 知乎 (zhihu.com) YOLOv8 是 ultralytics 公司在 2023 年 1月 10 号开源的 YOLOv5 的下一个重大更新版本&#xff0c;目前支持图像分类…

处理一对多的映射关系

一对多关系&#xff0c;比如说根据id查询一个部门的部门信息及部门下的员工信息 在Dept类中先添加List emps属性 1、collection DeptMapper.xml文件中 <resultMap id"deptAndEmpResultMap" type"Dept"><id property"did" column&qu…

2024新算法红嘴蓝鹊优化算法,原理详解,MATLAB代码免费获取

红嘴蓝鹊优化算法&#xff08;Red-billed blue magpie optimizer&#xff0c;RBMO&#xff09;是一种受自然启发的群智能优化算法。该算法的灵感来自红嘴蓝鹊的合作和有效的捕食行为。通过对红嘴蓝鹊的搜索、追逐、攻击和食物储存行为的模拟&#xff0c;建立了RBMO的数学模型。…

牛客网刷题 | BC113 数字三角形

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 KiKi学习了循环&am…

如何配置AI参数SK接口

如何配置AI参数SK接口 1、选择AI接口 接口选择&#xff1a;多个ai接口选择 百度文心一言&#xff1a;国内百度接口 第三方平台&#xff0c;无需自备GPT账号&#xff0c;无需反向代理&#xff0c;建议每次充值不要太多&#xff0c;不知道会不会关停跑路 自定义接口&#xff1a;…

牛客网刷题 | BC110 X形图案

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 KiKi学习了循环&am…

【算法】合并两个有序链表(easy)——递归算法

题解&#xff1a;合并两个有序链表(easy)——递归求解 目录 1.题目2.题解3.参考代码4.总结 1.题目 题目链接&#xff1a;LINK 2.题解 本题有两种解法&#xff0c; 一是用循环去处理 链接&#xff1a;【刷题记录】合并两个有序数组、移除元素二是用递归去处理 将在下面中说…

树莓派通过PCA9685控制FT2331M舵机(Python)

很久之前整过PWM舵机&#xff0c;刚好最近师弟需要&#xff0c;并且网上现有教程不是很完整&#xff0c;就整理一下。方便交流以及后面回顾。 首先要明确&#xff0c;在这个控制方式中需要用到哪些方面&#xff1a; 1、树莓派与PCA9685之间使用I2C通信 2、PCA9685通讯协议 3…

1. Mybatis基础操作

目录 1.1 需求 1.2 准备 1.3 删除 1.3.1 功能实现 1.3.2 日志输入 1.3.3 预编译SQL 1.3.3.1 介绍 1.3.3.2 SQL注入 1.3.3.3 参数占位符 1.4 新增 1.4.1 基本新增 1.4.2 主键返回 1.5 更新 1.6 查询 1.6.1 根据ID查询 1.6.2 数据封装 1.6.3 条件查询 1.6.4 参…

Virtualbox中对SD卡进行格式化和分区

系统&#xff1a;Ubuntu 22.04.4 LTS 方法一&#xff1a;在虚拟机的ubuntu系统中使用fdisk命令方式分区&#xff0c;具体请参考&#xff1a; imx6ull - 制作烧录SD卡-CSDN博客 方法二&#xff1a;使用Ubuntu自带GUI工具Disks Disks相比命令行工具更加简单无脑&#xff0c;用…

Nginx配置详细解释:(1)全局配置

自启动安装nginx:前面博客有解释 systemctl stop firewalld setenforce 0 [rootNode1 ~]#:mkdir /data [rootNode1 ~]#:cd /data [rootNode1 data]#:yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-devel [rootNode1 data]#:wget http://nginx.o…

数据恢复大革新!EasyRecovery16版本带来UIUX及性能的重大提升

全球领先的数据恢复解决方案提供商Ontrack与其中国区总代理近日共同宣布&#xff0c;其广受欢迎的数据恢复软件EasyRecovery16迎来了重大更新&#xff0c;版本号提升至v16.0.0.5。这一更新为用户带来了一系列值得关注的新功能和改进&#xff0c;进一步巩固了EasyRecovery在数据…

Apache Calcite - 自定义标量函数

前言 上一篇文章中我们介绍了calcite中内置函数的使用。实际需求中会遇到一些场景标准内置函数无法满足需求&#xff0c;这时候就需要用到自定义函数。在 Apache Calcite 中添加自定义函数&#xff0c;以便在 SQL 查询中使用自定义的逻辑。这对于执行特定的数据处理或分析任务…

1.1 OpenCV随手简记(一)

OpenCV学习篇 OpenCV (Open Source Computer Vision Library) 是一个开源的计算机视觉库&#xff0c;它提供了大量的算法和函数&#xff0c;用于图像处理、计算机视觉和机器学习等领域。 1. OpenCV 简介 1.1 OpenCV 的起源和发展 OpenCV 项目始于 1999 年&#xff0c;由 In…