一个处理Range List的面试题解法

大纲

  • 题目
  • 解法
    • Range
      • add
      • remove
    • Tools
    • RangeList
      • add
      • remove
  • 代码

最近看到一个比较有意思的面试题。题目不算难,但是想把效率优化做好,也没那么容易。
我们先看下题目

题目

// Task: Implement a class named 'RangeList'
// A pair of integers define a range, for example: [1, 5). This range includes integers: 1, 2, 3, and 4.
// A range list is an aggregate of these ranges: [1, 5), [10, 11), [100, 201)
/**
** NOTE: Feel free to add any extra member variables/functions you like.
*/
class RangeList {/**** Adds a range to the list* @param {Array<number>} range - Array of two integers that specify beginning andend of range.*/add(range) {// TODO: implement this}/**** Removes a range from the list* @param {Array<number>} range - Array of two integers that specify beginning andend of range.*/remove(range) {// TODO: implement this}/**** Convert the list of ranges in the range list to a string* @returns A string representation of the range list*/toString() {// TODO: implement this}
}
// Example run
const rl = new RangeList();
rl.toString(); // Should be ""
rl.add([1, 5]);
rl.toString(); // Should be: "[1, 5)"
rl.add([10, 20]);
rl.toString(); // Should be: "[1, 5) [10, 20)"
rl.add([20, 20]);
rl.toString(); // Should be: "[1, 5) [10, 20)"
rl.add([20, 21]);
rl.toString(); // Should be: "[1, 5) [10, 21)"
rl.add([2, 4]);
rl.toString(); // Should be: "[1, 5) [10, 21)"
rl.add([3, 8]);
rl.toString(); // Should be: "[1, 8) [10, 21)"
rl.remove([10, 10]);
rl.toString(); // Should be: "[1, 8) [10, 21)"
rl.remove([10, 11]);
rl.toString(); // Should be: "[1, 8) [11, 21)"
rl.remove([15, 17]);
rl.toString(); // Should be: "[1, 8) [11, 15) [17, 21)"
rl.remove([3, 19]);
rl.toString(); // Should be: "[1, 3) [19, 21)

这题大体的意思是:设计一个RangeList类,它保存了一批左闭右开的区间。它支持add操作,可以新增一个包含区间,但是可能会影响之前的区间,比如之前的区间是:[3,5) [7,9),新增区间[5,7)之后,区间就变成[3,9);它还支持remove操作,可以删除一个区间,也可能影响之前的区间,比如之前的区间是[3,9),删除[5,7)之后,变成[3,5) [7,9)。
在这里插入图片描述

还有一种特殊区间需要考虑,就是左右值相等的区间。比如[5,5)代表的是一个空区间。

解法

Range

首先我们设计一个Range类,它只是单个区间。

add

如果对其进行add操作,即新增一个区间,则要考虑这两个区间是否相交。如果相交,则返回一个重新整合过的区间;如果不相交,则抛出异常。
在这里插入图片描述

    # add the other range to this range.For example, [1, 5) add [5, 7) is [1, 7).# @param other - the other range to add to this range# @return - the new range after adding# @throws TypeError if other is not a Range object or a list of integers# @throws ValueError if other is not a list of 2 integers# @throws TypeError if other range is not overlap with this rangedef add(self, other) -> object:other = self.conv(other)if self.end < other.start or self.start > other.end:raise ValueError("other range must be overlap with this range")if self.start >= other.start and self.end <= other.end:return Range(other.start, other.end)if self.start >= other.start and self.end > other.end:return Range(other.start, self.end)if self.start < other.start and self.end <= other.end:return Range(self.start, other.end)if self.start < other.start and self.end > other.end:return Range(self.start, self.end)

remove

如果对其进行remove操作,即删除一个区间,也要考虑两个区间相交的情况。如果相交,则返回一个Range数组,其中可能0~2个区间。
在这里插入图片描述

    # remove the other range from this range.For example, [1, 5) remove [2, 3) is [1, 2) [3, 5).# @param other - the other range to remove from this range.the other range must be a Range object or a list of 2 integers# @return - a list of Range objects that are the result of removing other from this range# @throws TypeError if other is not a Range object or a list of integers# @throws ValueError if other is not a list of 2 integersdef remove(self, other) -> list:other = self.conv(other)if self.end < other.start or self.start > other.end:return [self]if self.start >= other.start and self.end <= other.end:return []if self.start >= other.start and self.end > other.end:return [Range(other.end, self.end)]if self.start < other.start and self.end <= other.end:return [Range(self.start, other.start)]if self.start < other.start and self.end > other.end:return [Range(self.start, other.start), Range(other.end, self.end)]

Tools

在设计完Range类后,我们还需要解决下面两个问题:

  • 被修正的区间有哪些
  • 需要调整位置的区间有哪些
    在这里插入图片描述
    上图中标红的表示可能要调整区间的区域。
    对于没有没有需要调整的区域,则要找到临近的区域。比如上图中第一组中,[7,8)需要找到[5,6)这组区间。如果是add操作,则需要将[7,8)插入到区间数组的[5,6)后面。
#!/usr/bin/env python
# -*- coding: utf-8; py-indent-offset:4 -*-
# ======================================================================================================================
# Copyrigth (C) 2024 fangliang <304646673@qq.com>
#
# This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later
# version.
#
# ======================================================================================================================from rangelist.range import Rangeclass Tools(object):          # search the index of the range which contains the value.First value is the index of the range where to compare with the value, # second value is True if the range contains the value, False otherwise.  # @param ranges - the list of ranges# @param value - the value to search# @param start_index - the start index of the ranges to search# @return the index of the range where to compare with the value, True if the range contains the value, False otherwise@staticmethoddef search(ranges, value, start_index = 0):if start_index < 0:start_index = 0end_index = len(ranges) - 1while start_index <= end_index:mid = (start_index + end_index) // 2if ranges[mid].start <= value and ranges[mid].end >= value:return (mid, True)elif ranges[mid].end < value:start_index = mid + 1else:end_index = mid - 1return (end_index, False)# search the index of the ranges which overlap with the search range.# First value is the index of the range where to compare with the value, second value is True if the range contains the value,# False otherwise.# @param ranges - the list of ranges# @param search_range - the range to search# @return a list of (index, overlap) of the ranges which overlap with the search range@staticmethoddef search_overlap(ranges, search_range):if search_range.start == search_range.end:return []start = Tools.search(ranges, search_range.start)end = Tools.search(ranges, search_range.end, start[0])index_list = [start]for i in range(start[0]+1, end[0]+1):index_list.append((i, True))return index_list

search_overlap方法返回的数据如下:

[(-1, False), (0, True), (1, True)]

-1代表对比的区间(可能是新增或者删除)的起始值在第0个区间的左侧。
True和False表示区间是否会调整(因为有覆盖)。

RangeList

RangeList用于保存一组Range序列。
这题的解法也主要依赖于其add和remove方法。

add

    # add a range to the list.For example, [[1, 5)] add [2, 3) is [[1, 5)].[[1, 5)] add [6, 8) is [[1, 5) [6, 8)].# @param other - the other range to compare with# @return True if the other range is overlap with this range, False otherwise# @throws TypeError if other is not a Range object or a list of integers# @throws ValueError if other is not a list of 2 integersdef add(self, other):other = Range.conv(other)indexes = Tools.search_overlap(self.ranges, other)del_start_index = -1for i in indexes:if i[1]:other = self.ranges[i[0]].add(other)if -1 == del_start_index:del_start_index = i[0]if -1 != del_start_index:del self.ranges[del_start_index : indexes[-1][0]+1]self.ranges.insert(del_start_index, other)elif len(indexes) > 0:self.ranges.insert(indexes[0][0]+1, other)return self

add方法会让一个Range不停“合并”被其覆盖的Range。然后删除被覆盖的Range,把新组合的Range插入到第一个覆盖的Range位置。
如果没有覆盖的区间,则在适当的位置插入。

remove

# remove the other range from this range.For example, [[1, 5) [10, 14)]] remove [2, 3) is [[1, 2) [3, 5) [10, 14)]].# @param other - the other range to remove from this range# @return - the new range after removing# @throws TypeError if other is not a Range object or a list of integers# @throws ValueError if other is not a list of 2 integersdef remove(self, other):other = Range.conv(other)indexes = Tools.search_overlap(self.ranges, other)del_start_index = -1range_list_from_remove_all = []for i in indexes:if i[1]:range_list_from_remove = self.ranges[i[0]].remove(other)if range_list_from_remove != None:range_list_from_remove_all.extend(range_list_from_remove)if -1 == del_start_index:del_start_index = i[0]if -1 != del_start_index:del self.ranges[del_start_index : indexes[-1][0]+1]self.ranges[del_start_index:del_start_index] = range_list_from_remove_allreturn self

remove方法则是让Range List中Range不停remove待删除Range,最后把切割的Range重新插入到Range List中。

代码

https://github.com/f304646673/rangelist.git

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

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

相关文章

【C++】C++中的【文件IO流】使用指南 [手把手代码演示] & [小白秒懂]

前言 大家好吖&#xff0c;欢迎来到 YY 滴 系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的《Linux》…

JavaEE-自定义SSM-编写核心-解析yml文件

3.3.1 加载yml文件 编写yaml工厂&#xff0c;用于加载yml文件 package com.czxy.yaml;import java.io.InputStream;/*** 用于处理 application.yml文件* 1. 加载application.yml文件* 2. yaml工具类进行解析* Map<String, Map<String, Map<....>> >* …

Linux使用二进制包安装MySQL

目录 一、软件包下载 二、上传软件包到Linux根目录 1、使用xftp将软件包上传到根目录 2、解压缩 三、准备工作 四、初始化软件 五、设置MySQL的配置文件 六、配置启动脚本 一、软件包下载 官网下载&#xff1a;MySQL :: Download MySQL Community Server 二、上传软件…

AWTK 开源串口屏开发(8) - 系统设置

AWTK 开源串口屏开发 - 系统设置 系统设置只是一个普通应用程序&#xff0c;不过它会用 默认模型 中一些内置的属性和命令&#xff0c;所以这里专门来介绍一下。 1. 功能 在这个例子会用到 默认模型 中一些下列内置的属性和命令&#xff1a; 内置属性 属性类型说明rtc_yea…

【Unity3D日常开发】Unity3D中设置Text行首不出现标点符号

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中会遇到Text的文本内容行首出现标点符号的情况&#xf…

PyTorch初探:基本函数与案例实践

正文&#xff1a; 在熟悉了PyTorch的安装和环境配置后&#xff0c;接下来让我们深入了解PyTorch的基本函数&#xff0c;并通过一个简单的案例来实践这些知识。 1. 基本函数 PyTorch的核心是张量&#xff08;Tensor&#xff09;&#xff0c;它类似于多维数组&#xff0c;但可以…

Cesium加载地图-高德影像

废话不多说&#xff0c;直接上代码 整体代码 <template><div id"cesiumContainer" style"height: 100vh;"></div><div id"toolbar" style"position: fixed;top:20px;left:220px;"><el-breadcrumb><…

hive面试题

0. 思维导图 1. 简述Hive♥♥ 我理解的&#xff0c;hive就是一款构建数据仓库的工具&#xff0c;它可以就结构化的数据映射为一张表&#xff0c;并且可以通过SQL语句进行查询分析。本质上是将SQL转换为MapReduce或者spark来进行计算&#xff0c;数据是存储在hdfs上&#xff0c;…

【word】论文、报告:①插入图表题注,交叉引用②快速插入图表目录③删改后一键更新

【word】①插入图表题注&#xff0c;②删改后一键更新 写在最前面插入题注交叉引用修改插入题注的文字格式快速插入图表目录 插入题注后有删改&#xff0c;实现编号一键更新 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你…

ubuntu安装mongod

1、安装 1.1包管理公钥导入 wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -执行结果截图如下&#xff1a; 1.2创建列表文件 lsb_release -dc 根据你的Codename 来修改下方对应的命令&#xff0c;如果你的是jammy&#xff0c;就修改为j…

Hive常见问题汇总

Hive和Hadoop的关系 Hive 构建在 Hadoop 之上&#xff0c; HQL 中对查询语句的解释、优化、生成查询计划是由 Hive 完成的 所有的数据都是存储在 Hadoop 中 查询计划被转化为 MapReduce 任务&#xff0c;在 Hadoop 中执行&#xff08;有些查询没有 MR 任务&#xff0c;如&…

防御保护---安全策略

文章目录 一.安全策略概述 概述&#xff1a; 安全策略的作用&#xff1a; 包过滤防火墙的安全风险 状态检测防火墙访问过程 安全策略与传统防火墙的区别 二.案例分析 基础配置&#xff1a;&#xff08;正常数通&#xff09; 安全策略配置 练习 一.安全策略概述 概述&#xff1…

OpenAI API 的最新动态:新一代的嵌入模型,更新 GPT-4 Turbo,更新 GPT-3.5 Turbo 以及降低 API 价格

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 OpenAI 正在推出新一代嵌入模型、新的 GPT-4 Turbo 和审查模型、新的 API 使用管理工具&#xff0c;而且很快就会降低 GPT-3.5 Turbo 的价格。 OpenAI…

vuepress搭建个人博客以及部署

vuepress&#xff0c;Vue 驱动的静态网站生成器&#xff0c;以 Markdown 为中心的项目结构&#xff0c;以最少的配置帮助你专注于写作。 vuepress官网 vuepress存在很多主题&#xff0c;也可以自定义设计主题&#xff0c;上传npm使用 这里采用vuepress-theme-hope主题模板进行制…

移动端应用(APP)如何设计测试用例?

为 APP 设计测试用例需要考虑移动设备的特殊性&#xff0c;如不同的操作系统、设备尺寸、硬件特性以及应用程序自身的特定功能。 以下是为APP设计测试用例时要考虑的内容&#xff1a; 1. 理解需求 熟悉APP的功能需求、用户故事和设计文档。 确定APP的目标用户群体、使用场景…

Leetcode刷题笔记题解(C++):1114. 按序打印(多线程)

思路&#xff1a; 保证A,B,C三个线程的顺序不会变&#xff0c;即优先级顺序的问题 A,B需要资源1&#xff0c;B,C需要资源2 A先占用资源1和资源2&#xff0c;A线程完了之后释放资源1不释放资源2&#xff0c;然后B线程占用资源1&#xff0c;A线程完了之后释放资源1和资源2&…

C++ 11 多线程库初步学习

在C11标准中&#xff0c;可以简单通过使用thread库&#xff0c;来管理多线程。 thread库可以看做对不同平台多线程API的一层包装&#xff1b;因此使用新标准提供的线程库编写的程序是跨平台的。 使用时需要#include <thread>头文件&#xff1b; #include <iostream&g…

Wpf 使用 Prism 实战开发Day16

客户端使用RestSharp库调用WebApi 动态加载数据 在MyDoTo客户端中&#xff0c;使用NuGet 安装两个库 RestSharp Newtonsoft.Json 一. RestSharp 简单的使用测试例子 当前章节主要目的是&#xff1a;对RestSharp 库&#xff0c;根据项目需求再次进行封装。下面先做个简单的使用…

瑞丽杂志引领潮流,VOSS眼镜概念店开启奢华新纪元!

近日&#xff0c;由《瑞丽》杂志社举办的2023第4届瑞丽轻奢品牌大赛&#xff0c;以“轻奢•悦藏”为主题的大赛已圆满结束&#xff0c;VOSS眼镜荣获&#xff1a;2023瑞丽轻奢品牌大赛「轻奢时尚风格奖」&#xff0c;作为眼镜行业唯一获此奖项的品牌&#xff0c;VOSS眼镜对此表示…

LeetCode.11. 盛最多水的容器

题目 题目链接 分析 这道题的意思就是让我们找两个下标&#xff0c;以这两个下标组成的线为底&#xff0c;高度取这两个位置对应数字的最小值为高&#xff0c;组成一个长方形&#xff0c;求长方形最大的面积可以为多少。 暴力的解法是什么&#xff1f;&#xff1f;&#xf…