228 汇总区间(模拟、双指针)

43 篇文章 0 订阅

1. 问题描述:

给定一个无重复元素的有序整数数组 nums 。返回恰好覆盖数组中所有数字的最小有序区间范围列表。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字 x 。列表中的每个区间范围 [a,b] 应该按如下格式输出:
"a->b" ,如果 a != b
"a" ,如果 a == b

示例 1:

输入:nums = [0,1,2,4,5,7]
输出:["0->2","4->5","7"]
解释:区间范围是:
[0,2] --> "0->2"
[4,5] --> "4->5"
[7,7] --> "7"

示例 2:

输入:nums = [0,2,3,4,6,8,9]
输出:["0","2->4","6","8->9"]
解释:区间范围是:
[0,0] --> "0"
[2,4] --> "2->4"
[6,6] --> "6"
[8,9] --> "8->9"

示例 3:

输入:nums = []
输出:[]

示例 4:

输入:nums = [-1]
输出:["-1"]

示例 5:

输入:nums = [0]
输出:["0"]

提示:

0 <= nums.length <= 20
-2 ^ 31 <= nums[i] <= 2 ^ 31 - 1
nums 中的所有值都互不相同,nums 按升序排列

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/summary-ranges

2. 思路分析:

① 首先需要读懂题目的意思,其实就是求解若干个连续数字的区间的起点与终点,观察题目的测试用例即可理解题目的意思,所以我们在循环中进行模拟通过判断相邻两个元素的差值是否是1来判断是否连续,需要使用一个pre变量来记录区间的起点,这样当发现相邻两个元素的差值不等于1的时候那么就需要往结果集中加入上一个的区间起点与终点对应的字符串,终点就为遍历元素的上一个元素,因为是是判断当前遍历元素与上一个元素的差值所以在循环结束之后需要额外处理最后一个元素,将结果加入到结果集中,其实就是模拟整个过程,注意其中的细节处理即可。

② 除了上面模拟求解的思路之外,我们还可以发现这道题目其实是一个双指针算法问题,可以定义两个指针l, r,判断相邻的两个元素是否相等,如果相等则r往右移否则就需要将两个指针对应范围的字符串加入到结果中,并且更新当前l,r指针为当前的nums[i],循环结束需要根据nums列表倒数两个元素的差值是否为1来添加最后的答案。

3. 代码如下:

from typing import List


class Solution:
    def summaryRanges(self, nums: List[int]) -> List[str]:
        if not nums: return []
        if len(nums) == 1: return [str(nums[0])]
        i = 1
        res, pre = list(), nums[0]
        while i < len(nums):
            # 不等于1的时候进行合并上一个区间
            if nums[i] - nums[i - 1] != 1:
                if pre != nums[i - 1]:
                    # 一个区间
                    res.append(str(pre) + "->" + str(nums[i - 1]))
                else:
                    # 只有一个元素
                    res.append(str(pre))
                pre = nums[i]
            i += 1
        # 处理最后一个元素, 如果相邻元素不相等那么把最后一个元素加入到结果集中, 如果相等那么需要将区间起始点加入到结果集中
        if len(nums) >= 2 and nums[-1] - nums[-2] != 1:
            res.append(str(nums[-1]))
        # [-1]表示倒数第一个元素, [-1]表示倒数第二个元素,以此类推
        elif len(nums) >= 2 and nums[-1] - nums[-2] == 1:
            res.append(str(pre) + "->" + str(nums[-1]))
        return res

双指针:

from typing import List


class Solution:
    # 双指针算法
    def summaryRanges(self, nums: List[int]) -> List[str]:
        if not nums: return list()
        elif len(nums) == 1: return [str(nums[0])]
        l, r = nums[0], nums[0]
        res = list()
        for i in range(1, len(nums)):
            if nums[i] != nums[i - 1] + 1:
                if l == r:
                    res.append(str(l))
                else:
                    res.append(str(l) + "->" + str(r))
                l = r = nums[i]
            else:
                r += 1
        # 处理nums最后一个区间
        if nums[i] == nums[i - 1] + 1:
            res.append(str(l) + "->" + str(r))
        else:
            res.append(str(nums[-1]))
        return res

python的第二种写法(固定左边位置然后移动右指针):

from typing import List


class Solution:
    def summaryRanges(self, nums: List[int]) -> List[str]:
        res = list()
        i = 0
        while i < len(nums):
            j = i + 1
            while j < len(nums) and nums[j] == nums[j - 1] + 1:
                j += 1
            # 满足下面的条件说明相邻的两个数字就不相等了
            if j == i + 1: res.append(str(nums[i]))
            else: res.append(str(nums[i]) + "->" + str(nums[j - 1]))
            i = j
        return res

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值