1.合并区间

题目描述:

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

示例 1:

1
2
3
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

1
2
3
输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

示例 3:

1
2
3
输入:intervals = [[4,7],[1,4]]
输出:[[1,7]]
解释:区间 [1,4] 和 [4,7] 可被视为重叠区间。

提示:

  • 1 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 104

解1.排序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        intervals.sort(key=lambda x:x[0])

        if len(intervals)==1:
            return intervals
        ans=[]
        ans.append(intervals[0])
        cur=0
        for i in range(1,len(intervals)):
            if intervals[i][0]<=ans[-1][1]:
                ans[-1][1] = max(ans[-1][1], intervals[i][1])
            else:
                ans.append(intervals[i])

        return ans   

解2.

通过一个cnt数组记录落位,cnt[i]>1的连续区间即为最终的区间 方法:对于一个区间[start,end],从cnt[start],cnt[start+1],…,cnt[end]全部加1 缺陷:[1,2],[3,4]本无法合并,按上述方法却可以合并,解决:*2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        mx = max(p[1] for p in intervals)

        diff = [0] * (mx * 2 + 2)
        for start, end in intervals:
            # 把区间 [start*2, end*2] 增加 1
            diff[start * 2] += 1
            diff[end * 2 + 1] -= 1

        ans = []
        sum_d = 0
        start = -1  # -1 表示尚未遇到合并后的区间左端点
        for i, d in enumerate(diff):
            sum_d += d  # 计算 diff 的前缀和
            if sum_d > 0:
                if start < 0:
                    start = i  # 合并后的区间左端点
            elif start >= 0:
                # i-1 是合并后的区间右端点
                # 由于乘 2 操作,区间左右端点都是偶数,所以 i-1 是偶数,i 是奇数,(i-1)/2 == floor(i/2)
                ans.append([start // 2, i // 2])
                start = -1
        # 注:最后一轮循环 sum_d == 0,我们不会漏掉最后一个区间
        return ans

轮转数组

题目描述:

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

1
2
3
4
5
6
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

1
2
3
4
5
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

提示:

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1
  • 0 <= k <= 105

题解:自己看,很简单

1
2
3
4
5
6
7
8
9
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        k=k%len(nums)
        p=nums[-k:]
        del nums[-k:]
        nums[0:0]=p

3.除了自身以数组的乘积

题目描述

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除了 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请 **不要使用除法,**且在 O(n) 时间复杂度内完成此题。

示例 1:

1
2
输入: nums = [1,2,3,4]
输出: [24,12,8,6]

示例 2:

1
2
输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

题解:

计算前乘积和后乘积,两者相乘即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        m = len(nums)
        suf = [1]*m
        for i in range(m-2, -1, -1):
            suf[i] = suf[i+1]*nums[i+1]
        
        per = 1
        for i, num in enumerate(nums):
            suf[i] *= per
            per *= num
        return suf
        #time O(m)
        #space O(1) 

4.Hard 缺失的第一个正数

题目描述:

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:

1
2
3
输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。

示例 2:

1
2
3
输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。

示例 3:

1
2
3
输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。

题解

意识到ans <= len(nums),然后依次判断i是否in nums即可

1
2
3
4
5
6
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        a=set(nums)
        for i in range(1,len(nums)+2):
            if i not in a:
                return i

还有一个题解我看着很有思路,虽然执行时间更长,但是包含了本地标记的思想,通过hashsize进行本地标记,挺有意思的,我把代码贴上去

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)
        hash_size = n + 1
        # 可能的答案为1, 2, ..., n + 1
        # 处理掉取值范围外的数
        for i in range(n):
            if nums[i] <= 0 or nums[i] >= hash_size:
                nums[i] = 0
        for i in range(n):
            if nums[i] % hash_size != 0:
                pos = (nums[i] % hash_size) - 1
                # 先取余再加,防止数字过大
                nums[pos] = (nums[pos] % hash_size) + hash_size
        for i in range(n):
            if nums[i] < hash_size:
                return i + 1
        return hash_size