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

这篇具有很好参考价值的文章主要介绍了一个处理Range List的面试题解法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

题目

// 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 and
	end of range.
	*/
	add(range) {
		// TODO: implement this
	}
	
	/**
	*
	* Removes a range from the list
	* @param {Array<number>} range - Array of two integers that specify beginning and
	end 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)。
一个处理Range List的面试题解法,python,list,python

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

解法

Range

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

add

如果对其进行add操作,即新增一个区间,则要考虑这两个区间是否相交。如果相交,则返回一个重新整合过的区间;如果不相交,则抛出异常。
一个处理Range List的面试题解法,python,list,python

    # 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 range
    def 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个区间。
一个处理Range List的面试题解法,python,list,python

    # 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 integers
    def 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类后,我们还需要解决下面两个问题:

  • 被修正的区间有哪些
  • 需要调整位置的区间有哪些
    一个处理Range List的面试题解法,python,list,python
    上图中标红的表示可能要调整区间的区域。
    对于没有没有需要调整的区域,则要找到临近的区域。比如上图中第一组中,[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 Range

class 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
    @staticmethod
    def search(ranges, value, start_index = 0):
        if start_index < 0:
            start_index = 0
        end_index = len(ranges) - 1
        while start_index <= end_index:
            mid = (start_index + end_index) // 2
            if ranges[mid].start <= value and ranges[mid].end >= value:
                return (mid, True)
            elif ranges[mid].end < value:
                start_index = mid + 1
            else:
                end_index = mid - 1
        
        return (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
    @staticmethod
    def 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 integers
    def add(self, other):
        other = Range.conv(other)
        
        indexes = Tools.search_overlap(self.ranges, other)
        del_start_index = -1
        for 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 integers
    def remove(self, other):
        other = Range.conv(other)
        
        indexes = Tools.search_overlap(self.ranges, other)
        del_start_index = -1
        range_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_all
        
        return self

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

代码

https://github.com/f304646673/rangelist.git文章来源地址https://www.toymoban.com/news/detail-819836.html

到了这里,关于一个处理Range List的面试题解法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python 开启5个线程处理list数据

    你可以使用如下代码来开启5个线程来处理列表数据: 在这个例子中,我们首先将要处理的列表划分成了5个子列表,每个子列表包含5个元素。然后,我们创建5个线程,每个线程分别处理一个子列表。最后,等待所有线程执行完毕。这样可以同时处理多个子列表,在一定程度

    2024年02月12日
    浏览(39)
  • labelImg无法保存classes文件的解决方法(IndexError: list index out of range)

    憨憨程序员,其实是有做读取旧classes保存到新classes功能的,但是看完代码发现就启动程序初始化的时候调用了一次,change save dir的时候根本没有调用。 我实力有限,只能靠比较愚蠢的方法解决了。 首先找到我们安装labelImg的地址,比如我就是放到conda环境里面,所以在这个

    2024年04月24日
    浏览(41)
  • 【Python】分割列表(list)方法详解:平均n等份、拆成一个一个的

    在日常开发中,有时候需要把一个大列表分割为固定的小列表,再进行相关处理。下面来看看详细的分割方法: 2.1 分割大列表为1个元素的小列表 2.2 分割大列表为3个元素的小列表 2.2.1 普通方法 2.2.2 改进方法 改进:用列表推导,结果都放到一个列表。 2.2.3 lambda方法 2.3 平均

    2024年02月03日
    浏览(44)
  • 根据一个List生成另外一个List,修改其中一个,导致另外一个List也在变化

    1、两个List复制         SysDic aSysDic = new SysDic();         aSysDic.setDkey(\\\"1\\\");         aSysDic.setDnote(\\\"12\\\");         SysDic bSysDic = new SysDic();         bSysDic.setDkey(\\\"2\\\");         bSysDic.setDnote(\\\"23\\\");         SysDic cSysDic = new SysDic();         cSysDic.setDkey(\\\"3\\\");         cSysDic.setDnote(\\\"34\\\");  

    2024年02月10日
    浏览(39)
  • Java进阶(List)——面试时List常见问题解读 & 结合源码分析

    List、Set、HashMap作为Java中常用的集合,需要深入认识其原理和特性。 本篇博客介绍常见的关于Java中List集合的面试问题,结合源码分析题目背后的知识点。 关于的Set的博客文章如下: Java进阶(Set)——面试时Set常见问题解读 结合源码分析 关于HaseMap的博客文章如下: Java进

    2024年02月06日
    浏览(56)
  • List常见面试问题

    Java中的List是一种存放有序的、可以重复的数据的集合,它允许重复元素的存在。List中的元素都有对应的一个序列号(索引)记录着元素的位置,因此可以通过这个序列号来访问元素。 ‍ Java中的List有三种实现方式:ArrayList、LinkedList和Vector。其中,ArrayList是基于数组实现的,

    2024年02月09日
    浏览(39)
  • 两个list如何根据一个list中的属性去过滤掉另一个list中不包含这部分的属性,用流实现

    要是需要GPT Plus账号的小伙伴可以联系我~ 你可以使用Java 8的流来实现这个功能。假设你有两个包含对象的List,每个对象有一个属性,你想根据一个List中的属性值来过滤掉另一个List中不包含这个属性值的对象。下面是一种使用流的方式来实现这个功能 在上面的例子中,我们

    2024年02月12日
    浏览(51)
  • Java经典的List面试题

    你知道的List都有哪些? ArrayList、LinkedList、Vector等。 List和Vector有什么区别? Vector是List接口下线程安全的集合。 List是有序的吗? List是有序的 ArrayList和LinkedList的区别?分别用在什么场景? ArrayList和LinkedList数据结构不一样 ArrayList用在查询较多的场合 LinkedList适用于插入较多

    2023年04月22日
    浏览(37)
  • 面试十七、list和deque

           一、 Deque           Deque容器是连续的空间,至少逻辑上看来如此,连续现行空间总是令我们联想到array和vector,array无法成长,vector虽可成长,却只能向尾端成长,而且其成长其实是一个假象,事实上(1) 申请更大空间 (2)原数据复制新空间 (3)释放原空间 三步骤,

    2024年04月26日
    浏览(26)
  • Java 集合List相关面试题

    📕作者简介: 过去日记 ,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。 📗本文收录于java面试题系列,大家有兴趣的可以看一看 📘相关专栏Rust初阶教程、go语言基础系列、spring教程等,大家有兴趣的可以看一看 📙Java并发编程系列,设计模式系列、

    2024年01月25日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包