抖音 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;顺序插入。如图所…

微信小程序播放音频

微信小程序是一种轻量化、便捷的应用程序&#xff0c;让用户可以直接在微信内享受各种服务。其中&#xff0c;播放音频是微信小程序中非常常见的功能之一。在本文中&#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…

华为手机开启adb的调试模式方法

1. 在设置->系统->关于手机&#xff0c;连续按几次"版本号" (注意: 在学生模式下不能使用) 2. 退到上一层&#xff0c;出现“开发人员选项”&#xff08;与“关于手机”并列&#xff09; 3. 选中“开发者选项”&#xff0c;选中“仅充电模式下允许ADB调式”&…

如何配置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…

React Query:高效管理API请求与缓存

React Query 是一个强大的状态管理库&#xff0c;专门用于处理数据获取、缓存和更新&#xff0c;尤其适合与 API 交互。它提供了许多高级特性&#xff0c;如自动缓存、离线状态管理、数据过期和重新获取等。 安装&#xff1a; npm install react-query导入并配置 React Query&…

RUST宏编程入门

宏指示符 在Rust的宏编程中&#xff0c;宏可以接受多种类型的参数&#xff0c;称为“指示符”。这些指示符帮助宏识别不同类型的代码片段&#xff0c;并相应地处理它们。 这里列出全部指示符&#xff1a; blockexpr 用于表达式ident 用于变量名或函数名itemliteral 用于字面常…

Internet Download Manager (IDM) 的优势

Internet Download Manager (IDM) 的优势 Internet Download Manager (IDM) 是一款流行的下载管理器&#xff0c;广泛用于加速和管理文件下载。以下是 IDM 的主要优势&#xff1a; 1. 下载加速 多线程下载&#xff1a;IDM 使用多线程技术&#xff0c;将下载的文件分成多个部…

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

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

【面试题-005】Java中的类加载机制有哪些

文章目录 Java中的类加载器有哪些什么是双亲委派模型 Java中的类加载器有哪些 Java中的类加载机制是指Java虚拟机&#xff08;JVM&#xff09;将类文件&#xff08;.class文件&#xff09;加载到内存中&#xff0c;并对类进行解释和初始化的过程。类加载机制包括加载、链接&am…

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

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