前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2023-09-16:用go语言,给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p , 它们表示一个长度为

2023-09-16:用go语言,给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p , 它们表示一个长度为

作者头像
福大大架构师每日一题
发布2023-09-19 15:42:57
2050
发布2023-09-19 15:42:57
举报
文章被收录于专栏:福大大架构师每日一题

2023-09-16:用go语言,给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p ,

它们表示一个长度为 n 且下标从 0 开始的数组 arr ,

数组中除了下标为 p 处是 1 以外,其他所有数都是 0 。

同时给你一个整数数组 banned ,它包含数组中的一些位置。

banned 中第 i 个位置表示 arr[banned[i]] = 0 ,题目保证 banned[i] != p 。

你可以对 arr 进行 若干次 操作。一次操作中,你选择大小为 k 的一个 子数组

并将它 翻转 。在任何一次翻转操作后,

你都需要确保 arr 中唯一的 1 不会到达任何 banned 中的位置。

换句话说,arr[banned[i]] 始终 保持 0 。

请你返回一个数组 ans ,对于 [0, n - 1] 之间的任意下标 i ,

ans[i] 是将 1 放到位置 i 处的 最少 翻转操作次数,

如果无法放到位置 i 处,此数为 -1 。

子数组 指的是一个数组里一段连续 非空 的元素序列。

对于所有的 i ,ans[i] 相互之间独立计算。

将一个数组中的元素 翻转 指的是将数组中的值变成 相反顺序 。

输入:n = 4, p = 0, banned = [1,2], k = 4。

输出:[0,-1,-1,1]。

来自左程云。

答案2023-09-16:

步骤如下:

1.创建一个奇数集合(oddSet)和一个偶数集合(evenSet)。

2.将所有奇数(除了p和banned中的位置)添加到oddSet中。

3.将所有偶数(除了p和banned中的位置)添加到evenSet中。

4.创建一个长度为n的数组ans,初始化全部为-1。

5.创建一个队列queue和两个指针l和r,初始化r=0。

6.将p放入队列queue中,r加1。

7.初始化level=0。

8.当l < r时,执行以下步骤:

  • • 取出队列头部元素cur。
  • • 将level赋值给ans[cur]。
  • • 计算cur左边和右边的范围,分别为left和right。
  • • 根据left的奇偶性,选择对应的集合curSet(如果left是偶数,则curSet为evenSet;否则为oddSet)。
  • • 在curSet中查找大于等于left的最小元素,并将其加入队列queue中,r加1。
  • • 从curSet中移除该元素。
  • • 重复以上步骤,直到curSet中没有大于等于left的元素。
  • • l加1。

9.更新level,重复步骤8直到l < r不成立。

10.返回ans。

时间复杂度:假设n为数组长度,遍历数组需要O(n)的时间复杂度,每次操作需要在集合中查找和移除元素,集合的查找和移除操作的时间复杂度为O(log n)。总体时间复杂度为O(n log n)。

空间复杂度:创建两个集合,集合的空间复杂度为O(n),创建一个队列,队列的空间复杂度为O(n),创建一个数组,数组的空间复杂度为O(n),总体空间复杂度为O(n)。

go完整代码如下:

代码语言:javascript
复制
package main

import (
    "fmt"

    "github.com/emirpasic/gods/sets/treeset"
)

func minReverseOperations(n int, p int, banned []int, k int) []int {
    oddSet := treeset.NewWithIntComparator()
    evenSet := treeset.NewWithIntComparator()

    for i := 1; i < n; i += 2 {
        oddSet.Add(i)
    }
    for i := 0; i < n; i += 2 {
        evenSet.Add(i)
    }

    for _, ban := range banned {
        oddSet.Remove(ban)
        evenSet.Remove(ban)
    }

    oddSet.Remove(p)
    evenSet.Remove(p)

    ans := make([]int, n)
    for i := range ans {
        ans[i] = -1
    }

    queue := make([]int, n)
    l := 0
    r := 0
    queue[r] = p
    r++

    level := 0
    for l < r {
        end := r
        for l < end {
            cur := queue[l]
            ans[cur] = level

            left := max(cur-k+1, k-cur-1)
            right := min(cur+k-1, n*2-k-cur-1)

            curSet := oddSet
            if (left & 1) == 0 {
                curSet = evenSet
            }

            _, ceiling := curSet.Find(func(index int, value interface{}) bool {
                if value.(int) >= left {
                    return true
                } else {
                    return false
                }
            })

            for ceiling != nil && ceiling.(int) <= right {
                queue[r] = ceiling.(int)
                r++
                curSet.Remove(ceiling)
                _, ceiling = curSet.Find(func(index int, value interface{}) bool {
                    if value.(int) >= left {
                        return true
                    } else {
                        return false
                    }
                })
            }

            l++
        }
        level++
    }

    return ans
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

func main() {
    n := 4
    p := 0
    banned := []int{1, 2}
    k := 4

    result := minReverseOperations(n, p, banned, k)
    fmt.Println(result)
}

在这里插入图片描述

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-09-16 20:28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 福大大架构师每日一题 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 步骤如下:
  • go完整代码如下:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档