Loading [MathJax]/jax/output/CommonHTML/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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
T-SQL应用实例
实验一:实验案例一(附加“练习用的可以附加的数据库--class”) 1、 在products表中查询出厂日期晚于2014年4月的水果信息。 select * from products where 出厂日期>'2014-04-30 ' 2、 在products表中分组查询所有水果,蔬菜,坚果的总成本。 select 种类,SUM(成本) 总成本 from products group by 种类 3、 在products表中查询所有水果的信息,并按照成本从高到低的顺序显示结果。 select * fro
L宝宝聊IT
2018/06/20
1K0
T-sql 高级查询( 5*函数 联接 分组 子查询)
T-SQL 高级查询是指在 T-SQL 中使用的复杂查询,可以用于执行复杂的操作。T-SQL 高级查询包括以下几类:
神秘泣男子
2024/06/03
1660
T-sql 高级查询( 5*函数 联接 分组 子查询)
浅谈 T-SQL语句操纵数据表
SQL是结构化查询语言,也是关系数据库的标准语言,各类数据库都支持SQL作为查询语言。 T-SQL 是标准SQL的加强版,除了标准的SQL命令之外,还对SQL命令进行了许多扩充。提供类似于程序语言的基本功能。如变量说明、流程控制、功能函数等。 当我们安装上数据库时,在其上常做的操作无非就是插(增)、删、改、查这四类,今天我们就来围绕这四个操作来谈一谈。 插入数据:
小手冰凉
2019/09/10
8310
浅谈 T-SQL语句操纵数据表
几道常见的SQL面试题,看你能答对几道?
马上又到了金九银十的找工作季节了,收集了几道比较常见的SQL面试题,在不看底部参考答案的情况下,看自己能做对几道。
SQL数据库开发
2024/04/25
1250
几道常见的SQL面试题,看你能答对几道?
T-SQL查询语句
1、SQL的组成: ①DML:数据操纵语句 select、insert、delete、update ②DDL:数据定义语句 create、alter、drop ③DCL:数据控制语句 grant、revoke 2、查询语句:select select 列名1,列名2,…… [into 新表名称] from 表名 [where 条件表达式] [order by 列名 排序方式] 排序 [group by 表达式] 分
L宝宝聊IT
2018/06/20
9920
SQL Server 语句操纵数据库
SQL语句的基本参数 create database benet #创建数据库,名为benet use benet #打开benet数据库 create table A1 #创建表为A1 ( 编号 int identity(1,1) not null, #identity(1,1)表示该列为标识列,种子和增量值都是1 学号 int pri
星哥玩云
2022/08/18
1.6K0
SQL Server 语句操纵数据库
一道SQL题的多种解法
自然的想法,寻找每个店铺是否连续三天都有销售额。利用现有的表,构造一个中间表,中间表既有当前日期的销售额,又有当前日期后两天的销售额,然后筛选销售额大于0的店铺名称即可。这种思路可以有(至少)两种实现方式。
数据森麟
2019/09/27
7220
一道SQL题的多种解法
那些年我们写过的T-SQL(中篇)
中篇的重点在于,在复杂情况下使用表表达式的查询,尤其是公用表表达式(CTE),也就是非常方便的WITH AS XXX的应用,在SQL代码,这种方式至少可以提高一倍的工作效率。此外开窗函数ROW_NUMBER的使用也使得数据库分页变得异常的容易,其他的一些特性使用相对较少,在需要时再查阅即可。 本系列包含上中下三篇,内容比较驳杂,望大家耐心阅读: 那些年我们写过的T-SQL(上篇):上篇介绍查询的基础,包括基本查询的逻辑顺序、联接和子查询 那些年我们写过的T-SQL(中篇):中篇介绍表表达式、集合运算符和开窗
用户1216676
2018/01/24
3.8K0
那些年我们写过的T-SQL(中篇)
SQLServer 学习笔记之超详细基础SQL语句 Part 4
-----------------------接Part 3-------------------
授客
2019/09/11
4980
那些年我们写过的T-SQL(上篇)
在当今这个多种不同数据库混用,各种不同语言不同框架融合的年代(一切为了降低成本并高效的提供服务),知识点多如牛毛。虽然大部分SQL脚本可以使用标准SQL来写,但在实际中,效率就是一切,因而每种不同厂商的SQL新特性有时还是会用到,这部分内容更是让人抓瞎,常常会由于一些很简单的问题花很久来搜索准确答案。赶脚俺弱小的智力已经完全无法记清楚常见的命令了,即使是用的最熟悉的T-SQL(SQL Server)。因此将最常见的T-SQL操作做个简单的总结,包括一些容易忽视的知识点和常见的开发样例。实话实说,现在开发中较
用户1216676
2018/01/24
3.3K0
那些年我们写过的T-SQL(上篇)
测试工程师SQL面试题
测试人员工作在工作中会用到SQL来辅助测试,求职时也常常会在笔试环节遇到各种各样的sql设计题目,张老师整理了一些工作中常用的sql知识点,希望对大家有所帮助。
张树臣
2018/09/29
5.3K0
测试工程师SQL面试题
高级SQL查询技巧——利用SQL改善和增强你的数据
关系数据库系统和混合/云数据管理解决方案的用户都可以使用SQL灵活地访问业务数据,并以创新的方式进行转换或显示。
云原生
2021/05/31
5.8K0
高级SQL查询技巧——利用SQL改善和增强你的数据
Leetcode No.185 部门工资前三高的所有员工
Employee 表包含所有员工信息,每个员工有其对应的工号 Id,姓名 Name,工资 Salary 和部门编号 DepartmentId 。
week
2021/11/29
2420
SQL Server常用Sql语句
30.使用COMPUTE BY子句可以对BY后面给出的列进行分组分组显示,并进行列的小计
Sindsun
2019/12/06
5.5K0
必须了解的十个高级 SQL 概念
随着数据量持续增长,对合格数据专业人员的需求也会增长。具体而言,对SQL流利的专业人士的需求日益增长,而不仅仅是在初级层面。
用户1516716
2021/03/23
1.1K0
sql基本增删改查
例:insert into Strdents (姓名,性别,出生日期) values (‘开心朋朋’,’男’,’1980/6/15′)
全栈程序员站长
2022/07/21
5150
SQL基础用法(实例一)
1 /* 2 3 4 2006年10月01日 5 6 SQL Server 数据库的基本操作 7 (1) 数据库的创建 8 (2) 数据表的创建以及相关约束的指定(含临时表) 9 (3) 数据的添/删/改 10 (4) 数据的查询 11 12 */ 13 14 (0)创建数据库 15 -- 指定数据库名称 16 -- (注:如果数据库名中包含空格可以使用[]将其标示) 17 create database [Super WC] 18 -- 关于
用户1112962
2018/07/03
9620
SQL员工部门表综合查询60题
CREATE DATABASE oa; USE oa; CREATE TABLE dept( deptno INT PRIMARY KEY, dname VARCHAR(20), loc VARCHAR(20) ) DROP TABLE emp CREATE TABLE emp( empno INT PRIMARY KEY, ename VARCHAR(20) NOT NULL, job VARCHAR(20) CHECK (job IN ('CLERK','SALESMAN','MANAGER','
Albert陈凯
2018/04/04
5.4K0
相关子查询 与非相关子查询
Ex1:select OrderId From Orders where EmployeeId=
张哥编程
2024/12/17
1360
好的数据库面试题集合
http://blog.csdn.net/sandyzhs/article/details/4059709
bear_fish
2018/09/20
1.8K0
相关推荐
T-SQL应用实例
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验