【269】滑动窗口_贪心_无向图_广度优先搜索

本文介绍了两种方法解决数组排序后查找目标值下标的问题:排序+遍历(O(nlogn))和一次遍历(O(n)),同时涉及半径为k的子数组平均值计算及数组中移除最大值和最小值的贪心策略。最后讨论了找出所有知晓秘密专家的算法,结合时间排序和图论搜索。
摘要由CSDN通过智能技术生成

2089.找出数组排序后的目标下标

方法一:排序+遍历

class Solution(object):
    def targetIndices(self, nums, target):
        ans = []
        nums.sort()
        for i, w in enumerate(nums):
            if w == target:
                ans.append(i)
        return ans
for i, w in enumerate(nums):
# i 表示数组下标
# w 表示数组下标对应的值
# enumerate 枚举

时间复杂度: O ( n log ⁡ n ) O(n\log n) O(nlogn)
空间复杂度: O ( log ⁡ n ) O(\log n) O(logn),排序的栈空间开销

方法二:一次遍历

class Solution(object):
    def targetIndices(self, nums, target):
        count1 = 0
        count2 = 0
        ans = []
        for num in nums:
            if num < target:
                count1 += 1
            elif num == target:
                count2 += 1
        for i in range(count1, count1 + count2):
            ans.append(i)
        return ans

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)


2090.半径为k的子数组平均值

滥用除法会导致结果相差一。因此遇到需要整除或向下取整这些东西,尽量只使用一次,即在获取最终结果
W n e w = W o l d − L e f t + R i g h t a n s = [ W n e w 2 × k + 1 ] W_{new} = W_{old} - Left + Right \\ ans = [\frac{W_{new}}{2\times k + 1}] Wnew=WoldLeft+Rightans=[2×k+1Wnew]

class Solution(object):
    def getAverages(self, nums, k):
        n = len(nums)
        ans = [-1] * n  # 全部设为-1,省去两个循环
        # 如果k满足条件
        if 2 * k + 1 <= n:
            temp = sum(nums[:2 * k])
            for i in range(k, n - k):
                temp += nums[i + k]
                ans[i] = temp // (2 * k + 1)
                temp -= nums[i - k]
        return ans

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)


2091.从数组中移除最大值和最小值

贪心算法

  • 都在前面一起删除,删除一次
  • 都在后面一起删除,删除一次
  • 一个在前面,一个在后面,分开删除,步骤加起来

数学语言表示

假设数组长度为 n n n, 最小值在 i i i, 最大值在 j j j, 并且 i < = j i<=j i<=j, 则按上面的三种情况分别删除

  • j + 1 j+1 j+1
  • n − i n-i ni
  • i + 1 + n − j i + 1 + n - j i+1+nj

取出三者最小值

class Solution(object):
    def minimumDeletions(self, nums):
        Max, maxIndex = float("-inf"), 0
        Min, minIndex = float("inf"), 0
        n = len(nums)
        for i in range(n):
            # 题目已经要求nums中的正数互不相同
            if nums[i] > Max:
                Max, maxIndex = nums[i], i
            if nums[i] < Min:
                Min, minIndex = nums[i], i
        if maxIndex < minIndex:
            maxIndex, minIndex = minIndex, maxIndex
        return min(maxIndex + 1, n - minIndex, minIndex + 1 + n - maxIndex)
# 取出极值的索引
minIndex = nums.index(min(nums))
maxIndex = nums.index(max(nums))

时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)


2092.找出知晓秘密的所有专家

  • 根据时间排序
  • 不同时间段建立无向图
  • 广度优先搜索
class Solution(object):
    def findAllPeople(self, n, meetings, firstPerson):
        isVisited = [0] * n
        # 专家0和firstPerson知道秘密
        isVisited[0], isVisited[firstPerson] = 1, 1
        # 按时间排列会议
        meetings.sort(key = lambda x : x[2])
        i, j = 0, 0
        while j < len(meetings):
            while j < len(meetings) and meetings[i][2] == meetings[j][2]:
                j += 1
            # 对每个时间段建无向图
            vertexs, edges = set(), defaultdict(list)
            for meeting in meetings[i : j]:
                vertexs.add(meeting[0])
                vertexs.add(meeting[1])
                edges[meeting[0]].append(meeting[1])
                edges[meeting[1]].append(meeting[0])
            # 先把已经知道秘密的成员提取出来
            q = deque([])
            for vertex in vertexs:
                if isVisited[vertex]:
                    q.append(vertex)
            # BFS
            while q:
                p = q.popleft()
                for v in edges[p]:
                    if isVisited[v] == 0:
                        isVisited[v] = 1
                        q.append(v)
            i = j
        ans = []
        for i in range(n):
            if isVisited[i] == 1:
                ans.append(i)
        return ans

时间复杂度: O ( m log ⁡ m + n ) O(m\log m+n) O(mlogm+n),排序需要 O ( m log ⁡ m ) O(m\log m) O(mlogm),广度优先搜索只需要 O ( n ) O(n) O(n)
空间复杂度: O ( m + n ) O(m+n) O(m+n),广度优先搜索需要的空间。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
滑动平均是一种常见的数据处理技术,通常用于平滑时间序列数据。滑动平均的基本思想是,在时间序列中,对一段连续的数据进行平均处理,得到一个新的平滑后的数据。 滑动平均通常使用滑动窗口来实现。滑动窗口是指在时间序列中,取固定长度的连续数据作为一个滑动窗口,然后将窗口向前滑动一个固定的步长,取下一个窗口,再进行平均处理。这样就可以得到一系列平滑后的数据。 下面是一个简单的例子,演示如何使用Python实现滑动平均。 ```python import numpy as np # 生成一个随机时间序列 np.random.seed(0) data = np.random.randn(100) # 定义滑动窗口的长度和步长 window_size = 10 step = 1 # 计算滑动平均 smoothed_data = [] for i in range(0, len(data) - window_size + 1, step): window_data = data[i:i+window_size] smoothed_data.append(np.mean(window_data)) # 打印平滑后的数据 print(smoothed_data) ``` 在上面的例子中,我们首先生成了一个随机时间序列,然后定义了滑动窗口的长度和步长。接着,我们遍历整个时间序列,每次取一个固定长度的滑动窗口,并计算窗口中数据的平均值,将平均值添加到平滑后的数据列表中。最后,我们打印出平滑后的数据。 需要注意的是,这个例子中的滑动平均是简单平均法,也就是说,每个窗口中的数据权重相等。如果需要使用其他的加权平均法,可以根据需要进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值