Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >keep move!滑动窗口中位数与滑动魔方

keep move!滑动窗口中位数与滑动魔方

作者头像
掘金安东尼
发布于 2022-09-19 03:04:55
发布于 2022-09-19 03:04:55
25900
代码可运行
举报
文章被收录于专栏:掘金安东尼掘金安东尼
运行总次数:0
代码可运行

这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

前面已经带来 2 篇关于滑动窗口的掘文,传送门:

前文说到,即使都是窗口滑动,但“怎么滑”,滑动后“怎么做”,里面就存在很大的解题思路的差异!

本篇继续来探索、发现、记录这个差异~ 当然也不能忘了解题中的感受分享~

滑动窗口中位数

题目:给你一个数组 nums,有一个长度为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。

中位数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
中位数是有序序列最中间的那个数。如果序列的长度是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数,例如:

[2,3,4],中位数是 3
[2,3],中位数是 (2 + 3) / 2 = 2.5

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
给出 nums = [1,3,-1,-3,5,3,6,7],以及 k = 3。

窗口位置                      中位数
---------------               -----
[1  3  -1] -3  5  3  6  7       1
 1 [3  -1  -3] 5  3  6  7      -1
 1  3 [-1  -3  5] 3  6  7      -1
 1  3  -1 [-3  5  3] 6  7       3
 1  3  -1  -3 [5  3  6] 7       5
 1  3  -1  -3  5 [3  6  7]      6

因此,返回该滑动窗口的中位数数组 [1,-1,-1,3,5,6]

有了前面两篇文章的基础,老观众肯定知道:此题解题的关键肯定不在于窗口滑动,而在于“滑动的过程中怎么去求这个中位数?”

暴力求解:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 计算中位数---奇数情况
function calMedianOdd(sortedWindow) {
    const len = sortedWindow.length;
    return sortedWindow[Math.floor(len / 2)];
}
// 计算中位数---偶数情况
function calMedianEven(sortedWindow) {
    const len = sortedWindow.length;
    return (sortedWindow[Math.floor(len / 2)] +
        sortedWindow[Math.floor(len / 2) - 1]) / 2;
}

不出意外,会报错:超出时间限制,因为每次发生窗口滑动了,还要进行排序,时间复杂度大于 O(n * k),还取决于排序算法;

那有没有什么办法在滑动窗口的时候能利用上一个滑窗的状态?

答案肯定是“有的”,不然到这就剧终了~

有一个很重要的条件不能忽略:每次移动时,在删除左边界元素与加入右边界元素之前,窗口内的内容必然有序;

所以,在我们初始化排完顺序之后,发生第一次窗口的滑动时,希望找到右边界元素插入的正确位置(splice),以保障插入后直接就是有序的了,不用再排序了;

于是乎:问题变成了 —— 在有序数列中找到一个位置,于是乎,【二分法】登场!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 二分搜索
function binarySearch(sortedArr, target) {
    // 这里的搜索区间是左闭右开
    let left = 0;
    let right = sortedArr.length;
    while (left < right) {
        const mid = Math.floor((left + right) / 2);
        // 不能舍去mid
        if (sortedArr[mid] > target) {
            right = mid;
        } else if (sortedArr[mid] <= target) {
            left = mid + 1;
        }
    }
    return right;
}

完整算法就不贴了,思路已经有了,具体实现就自己敲敲打打吧~

小结:滑动窗口的重点不是使窗口滑动就完事了,重点是下一窗口的滑动怎样利用上一窗口的“特性”,比如:有序;

滑动魔方

题目:在一个 2 x 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, 以及一块空缺用 0 来表示.一次移动定义为选择 0 与一个相邻的数字(上下左右)进行交换. 最终当板 board 的结果是 [1,2,3,4,5,0] 谜板被解开。 给出一个谜板的初始状态,返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 -1 。

示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
输入:board = [[1,2,3],[4,0,5]]
输出:1
解释:交换 051 步完成

输入:board = [[1,2,3],[5,4,0]]
输出:-1
解释:没有办法完成谜板

输入:board = [[4,1,2],[5,0,3]]
输出:5
解释:
最少完成谜板的最少移动次数是 5一种移动路径:
尚未移动: [[4,1,2],[5,0,3]]
移动 1 : [[4,1,2],[0,5,3]]
移动 2 : [[0,1,2],[4,5,3]]
移动 3 : [[1,0,2],[4,5,3]]
移动 4 : [[1,2,0],[4,5,3]]
移动 5 : [[1,2,3],[4,5,0]]

哇,这个读完题就能感觉到难度,有点像是玩魔方,把一个数组丢到一个算法里进行“旋转”,最后得出一共走了几步;

解题关键词:广度优先搜索(BFS);

直白来说就是穷举,每走一步,列出所有变化,然后与目标值匹配,如果没有,再多走一步,然后再穷举、匹配,搜索完成后,还没有匹配的,则返回 -1;

本题当中,由于是一个二维数组,所以,注意条件是 与一个相邻的数字(上下左右)进行交换

例如 0 所在的位置是 x,对于每一个与 x 相邻的位置 y,我们将 statusx 与 statusy 进行交换,即等同于进行了一次操作;

关键代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
...
// 枚举 status 通过一次交换操作得到的状态
    const get = (status) => {
        const ret = [];
        const array = Array.from(status);
        const x = status.indexOf('0');
        for (const y of neighbors[x]) {
            [array[x], array[y]] = [array[y], array[x]];
            ret.push(array.join(''));
            [array[x], array[y]] = [array[y], array[x]];
        }
        return ret;
    }
...

其实本题还有另一种思路:在很久前写过一篇《狄克斯特拉算法》,能给到一些启发~~ (●'◡'●) BFS,yyds!


OK,至此,我们前前后后通过滑动窗口认识了:单调队列、二分法、广度优先搜索;

有一说一,滑动窗口,有点东西!!

我是掘金安东尼,公众号同名,输出暴露输入,技术洞见生活,下次再会~~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
有了BFS,困难的谜题也不过如此,一个模板就够了
BFS,其英文全称是Breadth First Search,中文叫广度优先搜索,从根节点开始遍历,然后遍历根节点的子节点,所有子节点访问到后再遍历子节点的子节点,也就是根据深度每一层每一层的遍历。一般会用到队列和字典这两种数据结构。队列用于存储枚举的节点集合,字典用于记录节点是否访问过,用于排重。
兜兜转转
2023/03/06
2740
双指针/滑动窗口/移动队列
Never stop learning, beacuse life never stops teaching. 不要停止学习, 因为人生总有东西可教 there is always more you don`t know. 无重复字符最长子串 双指针/滑动窗口/移动队列 无重复字符最长子串 package cn.com.codingce.aaclengthoflongestsubstring; import java.util.Arrays; import java.util.HashMap; impor
后端码匠
2021/08/20
4940
LeetCode 773. 滑动谜题(BFS 地图状态转换的最短距离)
在一个 2 x 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, 以及一块空缺用 0 来表示.
Michael阿明
2020/07/13
9290
【刷穿 LeetCode】480. 滑动窗口中位数(困难)
一个直观的做法是:对每个滑动窗口的数进行排序,获取排序好的数组中的第 k / 2 和 (k - 1) / 2 个数(避免奇偶数讨论),计算中位数。
宫水三叶的刷题日记
2021/02/20
4290
【图论搜索专题】灵活运用多种搜索方式进行求解 Ⅱ(含启发式搜索)
Tag : 「BFS」、「最小步数」、「AStar 算法」、「启发式搜索」在一个 2 x 3 的板上(board)有 块砖瓦,用数字 1~5 来表示, 以及一块空缺用 来表示.一次移动定义为选择 与一个相邻的数字(上下左右)进行交换.最终当板 board 的结果是 谜板被解开。给出一个谜板的初始状态,返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 。
宫水三叶的刷题日记
2021/12/02
4360
004. 寻找两个正序数组的中位数 | Leetcode题解
给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。
苏南
2020/12/16
1.5K0
004. 寻找两个正序数组的中位数 | Leetcode题解
​LeetCode刷题实战480:滑动窗口中位数
算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试。所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 !
程序员小猿
2021/12/27
4530
​LeetCode刷题实战480:滑动窗口中位数
【python-leetcode480-双堆】滑动窗口的中位数
中位数是有序序列最中间的那个数。如果序列的大小是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
西西嘛呦
2020/08/26
8060
golang刷leetcode 滑动窗口(4)滑动窗口中位数
中位数是有序序列最中间的那个数。如果序列的大小是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
golangLeetcode
2022/08/02
5340
搞定大厂算法面试之leetcode精讲5.二分查找
搞定大厂算法面试之leetcode精讲5.二分查找 视频教程(高效学习):点击学习 目录: 1.开篇介绍 2.时间空间复杂度 3.动态规划 4.贪心 5.二分查找 6.深度优先&广度优先 7.双指针 8.滑动窗口 9.位运算 10.递归&分治 11剪枝&回溯 12.堆 13.单调栈 14.排序算法 15.链表 16.set&map 17.栈 18.队列 19.数组 20.字符串 21.树 22.字典树 23.并查集 24.其他类型题 二分搜索 时间复杂度O(logn) 步骤: 从数组中间的元素开始,如果中
全栈潇晨
2021/11/24
3270
LeetCode 480. 滑动窗口中位数(大小堆升级版+set实现)
中位数是有序序列最中间的那个数。 如果序列的大小是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
Michael阿明
2020/07/13
5510
前端leetcde算法面试套路之双指针
上一 part 刚写完二分和滑窗,他们都属于特殊的双指针方法,所以这一 part 直接汇总一下除了特殊的二分和滑窗外的其他双指针写法
js2030code
2022/11/02
4830
LeetCode 295.数据流的中位数 - JavaScript
题目描述:中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
心谭博客
2020/04/21
7180
前端leetcde算法面试套路之双指针
上一 part 刚写完二分和滑窗,他们都属于特殊的双指针方法,所以这一 part 直接汇总一下除了特殊的二分和滑窗外的其他双指针写法
js2030code
2022/12/15
2370
滑动窗口详解
暴力解法:枚举出所有的情况,然后判断长度和区间和,这种方法的时间复杂度最优为O(n^2)
2的n次方
2024/10/15
1250
滑动窗口详解
BFS+DFS终结游戏题目
题目描述:在一个 2 x 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, 以及一块空缺用 0 来表示.
公众号guangcity
2020/07/02
4190
【滑动窗口专题】一道结合众多知识点的滑窗综合题
Tag : 「枚举」、「哈希表」、「排序」、「前缀和」、「二分」、「滑动窗口」、「双指针」
宫水三叶的刷题日记
2022/04/06
2980
TypeScript算法题实战——数组篇(二分法、双指针、滑动窗口、螺旋矩阵的TS解法)
TypeScript 是由微软开发的一款开源的编程语言,TypeScript 是 Javascript 的超集,遵循最新的 ES6、ES5 规范,TypeScript 扩展了 JavaScript 的语法。TypeScript 更像后端 Java、C#这样的面向对象语言,可以让 JavaScript 开发大型企业项目。谷歌也在大力支持 Typescript 的推广,谷歌的 angular2.x+ 就是基于 Typescript 语法,最新的 Vue 、React 也可以集成 TypeScript。Nodejs 框架中的 Nestjs、midway 中用的就是 TypeScript 语法。
中杯可乐多加冰
2024/08/02
890
LeetCode *480. 滑动窗口中位数(滑动窗口)
中位数是有序序列最中间的那个数。如果序列的长度是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
SakuraTears
2022/01/13
4060
前端学数据结构与算法(十二):有趣的算法 - 多指针与滑动窗口
如果说如何用算法高效有趣的解决某些问题,那多指针和滑动算法绝对是算其中的佼佼者。这也是笔者最初接触算法时觉得最有意思的一点,因为解决的问题是熟悉的,但配方却完全不同,本章我们从一个简单的交集问题出发,一步步的认识到多指针及滑动窗口解决某些问题时的巧妙与高效,本章主要以解LeetCode里高频题为参考~
飞跃疯人院
2020/11/19
5960
推荐阅读
相关推荐
有了BFS,困难的谜题也不过如此,一个模板就够了
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验