Loading [MathJax]/jax/output/CommonHTML/jax.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >完美世界,最大规模裁员

完美世界,最大规模裁员

作者头像
宫水三叶的刷题日记
发布于 2024-06-26 01:32:19
发布于 2024-06-26 01:32:19
11600
代码可运行
举报
运行总次数:0
代码可运行

题目描述

平台:LeetCode

题号:768

这个问题和“最多能完成排序的块”相似,但给定数组中的元素可以重复,输入数组最大长度为 2000,其中的元素最大为 10^8

arr 是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。

之后再连接起来,使得连接的结果和按升序排序后的原数组相同。

我们最多能将数组分成多少块?

示例 1:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入: arr = [5,4,3,2,1]

输出: 1

解释:
将数组分成2块或者更多块,都无法得到所需的结果。
例如,分成 [5, 4], [3, 2, 1] 的结果是 [4, 5, 1, 2, 3],这不是有序的数组。 

示例 2:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入: arr = [2,1,3,4,4]

输出: 4

解释:
我们可以把它分成两块,例如 [2, 1], [3, 4, 4]。
然而,分成 [2, 1], [3], [4], [4] 可以得到最多的块数。 

注意:

  • arr 的长度在
[1,2000]

之间。

  • arr[i] 的大小在
[0,108]

之间。

贪心 + 构造

一种容易想到的构造方法,是与目标序列(已排升序的数组 clone)做区间比较。

由于题目要求尽可能划分出多的区间,我们可以从前往后处理 arrclone 时统计区间内数的情况,若有 arr[i...j]clone[i...j] 词频完全相同,可知 arr[i...j] 可通过内部排序调整为 clone[i...j],此时我们将范围

[i...j]

划分为一个区间,然后继续往后处理直到整个数组处理完。

容易证明该做法的正确性:可从边界开始进行归纳分析,起始两者均从下标为 0 的位置进行扫描。假设最优解和贪心解的第一个区间的结束位置相同,问题就会归结到子问题上(即双方均从相同的子数组起始位置开始构造),因此无须额外证明;而当起始位置相同,结束位置不同时,假设分别为

clone[i...j1]

arr[i...j2]

,则必然有

j1>j2

(因为如果有

j1<j2

,那么在

arr

扫描到前者时已经满足划分区间的条件,已经会停下来,即与贪心决策逻辑冲突),而当

j1>j2

时,我们可以将最优解中的区间

clone[i...j1]

进一步划分为

clone[i...j2]

clone[j2+1...j1]

两段,同时不影响后续的构造过程,使得最终划分的区间数增大,即与最优解本身无法划分冲突。

根据数值之间满足严格全序,可知当

j1>j2

j1<j2

均不满足时,必然有

j1=j2

为真。

综上,我们证明了对于相同起点,贪心解与最优解结束位置必然相同,从而证明贪心解区间数与最优解相等。

于是原问题转换为如何快速对两数组(原数组 arr 和目标数组 clone)进行词频比较,由于数值的范围为 10^8,如果使用最裸的词频对比方案的话,需要先进行离散化,最终算法的复杂度为

O(nlogn+n2)

更好的解决方案是使用哈希表进行计数,同时维护当前计数不为 0 的数值数量 tot

具体的,当我们处理

arr[i]

时,我们在哈希表中对

arr[i]

进行计数加一,而在处理

clone[i]

时,对

clone[i]

进行计数减一。从而将词频比较的复杂度从

O(n2)

下降到

O(n)

Java 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public int maxChunksToSorted(int[] arr) {
        int[] clone = arr.clone();
        Arrays.sort(clone);
        int n = arr.length, ans = 0;
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0, tot = 0; i < n; i++) {
            int a = arr[i], b = clone[i];
            if (map.getOrDefault(a, 0) == -1) tot--;
            else if (map.getOrDefault(a, 0) == 0) tot++;
            map.put(a, map.getOrDefault(a, 0) + 1);
            if (map.getOrDefault(b, 0) == 1) tot--;
            else if (map.getOrDefault(b, 0) == 0) tot++;
            map.put(b, map.getOrDefault(b, 0) - 1);
            if (tot == 0) ans++;
        }
        return ans;
    }
}

Python 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def maxChunksToSorted(self, arr: List[int]) -> int:
        clone = sorted(arr)
        n, ans, tot = len(arr), 0, 0
        mapping = defaultdict(int)
        for i in range(n):
            a, b = arr[i], clone[i]
            if mapping.get(a, 0) == -1:
                tot -= 1
            elif mapping.get(a, 0) == 0:
                tot += 1
            mapping[a] = mapping.get(a, 0) + 1
            if mapping.get(b, 0) == 1:
                tot -= 1
            elif mapping.get(b, 0) == 0:
                tot += 1
            mapping[b] = mapping.get(b, 0) - 1
            if tot == 0:
                ans += 1
        return ans

TypeScript 代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function maxChunksToSorted(arr: number[]): number {
    let clone = [...arr].sort((a,b)=>a-b)
    let n = arr.length, ans = 0
    const map = new Map<number, number>()
    for (let i = 0, tot = 0; i < n; i++) {
        const a = arr[i], b = clone[i]
        if (!map.has(a)) map.set(a, 0)
        if (map.get(a) == 0) tot++
        else if (map.get(a) == -1) tot--;
        map.set(a, map.get(a) + 1)
        if (!map.has(b)) map.set(b, 0)
        if (map.get(b) == 0) tot++
        else if (map.get(b) == 1) tot--
        map.set(b, map.get(b) - 1)
        if (tot == 0) ans++
    }
    return ans
};
  • 时间复杂度:
O(nlogn)
  • 空间复杂度:
O(n)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-06-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 宫水三叶的刷题日记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
2596 售货员的难题
2596 售货员的难题 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 钻石 Diamond 题目描述 Description 某乡有n个村庄(1<n<=15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。 输入描述 Input Descrip
attack
2018/04/12
6040
【综合笔试题】难度 2/5,简单且经典面试题
给定两个大小相等的数组 nums1 和 nums2,nums1 相对于 nums 的优势可以用满足 nums1[i] > nums2[i] 的索引 i 的数目来描述。
宫水三叶的刷题日记
2023/02/27
3260
【算法/训练】:贪心(算法理论学习及实践)
🔥 贪心算法(greedy algorithm,又称贪婪算法),在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。
IsLand1314
2025/06/02
1460
【算法/训练】:贪心(算法理论学习及实践)
【综合笔试题】难度 2.5/5,状态机序列 DP 运用题
给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。
宫水三叶的刷题日记
2022/12/30
3050
【综合笔试题】难度 2.5/5,状态机序列 DP 运用题
当时说大概率在面试不会出的题目,在旷视二面出了
而投稿的题目,我印象很深,当时我还在日更 LC 题解的时候,曾作为 LC 每日一题出过。
宫水三叶的刷题日记
2024/03/13
1530
当时说大概率在面试不会出的题目,在旷视二面出了
LeetCode Weekly Contest 45解题思路
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014688145/article/details/77148515
用户1147447
2019/05/26
4710
【区间和专题の前缀和】线段树(动态开点)运用题
这是 LeetCode 上的「732. 我的日程安排表 III」,难度为「困难」。
宫水三叶的刷题日记
2022/06/21
7950
【图论搜索专题】并查集优化双向 BFS
给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶。
宫水三叶的刷题日记
2021/12/13
7180
LeetCode 454: 四数相加 II 4Sum II
给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。
爱写bug
2019/12/16
6590
【滑动窗口专题】一道结合众多知识点的滑窗综合题
Tag : 「枚举」、「哈希表」、「排序」、「前缀和」、「二分」、「滑动窗口」、「双指针」
宫水三叶的刷题日记
2022/04/06
3030
分治、动态规划、回溯、贪心一锅炖
但如果你看过《事实》这本书,你就不会被大脑中的惯性思维所影响。只要我们理解算法思想的关键点,多做题练习并加深理解记忆。其实算法思想就像切菜一样简单。
童欧巴
2020/06/17
7540
Greedy & Violent
1 2 3//坐标缩小后就可以更方便的选择 double pos = (double)i / n * (n + m);//原来雕像的位置 ans += fabs(pos - floor(pos + 0.5))/(n + m);//*n+m后就选四舍五入最近的
radaren
2018/08/28
5840
leetcode 395. 至少有 K 个重复字符的最长子串----双指针篇5,滑动窗口篇4,新人理解递归必看篇!!
本题要求的一个最长的子字符串的长度,该子字符串中每个字符出现的次数都最少为 kk。
大忽悠爱学习
2021/11/15
7140
LeetCode动画 | 1338.数组大小减半
今天分享一个LeetCode题,题号是1338,标题是数组大小减半,题目标签是贪心算法和数组。
乔戈里
2020/02/24
4600
JavaScript刷LeetCode拿offer-贪心算法
学习算法的时候,总会有一些让人生畏的名词,比方动态规划,贪心算法 等,听着就很难;而这一 part 就是为了攻破之前一直没有系统学习的 贪心算法;
hellocoder2028
2022/11/02
3960
leetcode周赛(195)
给你一个整数数组 arr 和一个整数 k ,其中数组长度是偶数,值为 n 。现在需要把数组恰好分成 n / 2 对,以使每对数字的和都能够被 k 整除。
你的益达
2020/08/05
5090
2024 前六周数据出炉:进击的华为
据机构数据显示,今年前六周,苹果公司在中国的 iPhone 销量同比下降 24%,而华为手机销量增加 64%。
宫水三叶的刷题日记
2024/03/13
1320
2024 前六周数据出炉:进击的华为
【算法】分治思想、动态规划、回溯、贪心算法
分治算法思想很大程度上是基于递归的,也比较适合用递归来实现。顾名思义,分而治之。一般分为以下三个过程:
微芒不朽
2022/09/06
9070
用javascript分类刷leetcode4.贪心(图文视频讲解)
贪心法,又称贪心算法,贪婪算法,在对问题求解时,总是做出在当前看来最好的选择,期望通过每个阶段的局部最优选择达到全局最优,但结果不一定最优
hellocoder2028
2022/12/15
3460
搞定大厂算法面试之leetcode精讲4.贪心
贪心法,又称贪心算法,贪婪算法,在对问题求解时,总是做出在当前看来最好的选择,期望通过每个阶段的局部最优选择达到全局最优,但结果不一定最优
全栈潇晨
2021/11/23
6080
搞定大厂算法面试之leetcode精讲4.贪心
推荐阅读
相关推荐
2596 售货员的难题
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验