首页 > 其他分享 >2023-09-16:用go语言,给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p , 它们表示一个长度为 n 且下标从 0 开始的数组 arr , 数组中除了下标为 p 处是 1

2023-09-16:用go语言,给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p , 它们表示一个长度为 n 且下标从 0 开始的数组 arr , 数组中除了下标为 p 处是 1

时间:2023-09-16 20:50:42浏览次数:39  
标签:下标 cur int banned 整数 数组 ans return

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完整代码如下:

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)
}

在这里插入图片描述

标签:下标,cur,int,banned,整数,数组,ans,return
From: https://www.cnblogs.com/moonfdd/p/17707263.html

相关文章

  • 基础二分算法:整数二分、浮点二分
    1、整数二分以acwing789为例,题目要求如下:第一行输入整数n和q,表示数组长度和询问个数。第二行输入数组,包含n个整数。接下来q行,每一行一个整数k,表示一个问询元素。要求输出q行,每行包含两个整数,表示所求元素的起始位置和终止位置。如果数组中不存在该元素,则返回-1-1。#inc......
  • 2023-09-16:用go语言,给你一个整数 n 和一个在范围 [0, n - 1] 以内的整数 p , 它们表示
    2023-09-16:用go语言,给你一个整数n和一个在范围[0,n-1]以内的整数p,它们表示一个长度为n且下标从0开始的数组arr,数组中除了下标为p处是1以外,其他所有数都是0。同时给你一个整数数组banned,它包含数组中的一些位置。banned中第i个位置表示arr[banned[i]]=......
  • java == 和 equals 和 128以下整数
    Integera=127;Integerb=127;System.out.println(a==b);打印值为true而Integera=128;Integerb=128;System.out.println(a==b);打印值为false 因为:在Java中,不应该以这种方式比较对象。当您像a==b那样比较它们时,您比较的是引用,而不是值,值......
  • 35-列表-元素删除的3种方式-删除本质是数组元素拷贝
        删除和增加本质就是数组元素拷贝       ......
  • leet code 删除有序数组中的重复项 I II
    26.删除有序数组中的重复项80.删除有序数组中的重复项II总结反思这两个题目,虽然难度程度一个是简单,一个是中等,都不是特别难。但是都没有解决。因为这两道题目都是运用双指针解决的,证明自己对双指针的掌握程度还不是很熟练。反思:为什么没有解出来?又或者,经过一段时间之后是否能够......
  • 数组(二)
    数组(二)今日份学习为数组的基本操作。分为以下几个部分:遍历数组,填充数组元素,替换数组元素,对数组进行排序以及复制数组。遍历数组通常遍历数组是通过使用for循环来实现的。需注意的是,遍历二维数组需要使用双层for循环,通过数组的length属性可获得数组的长度。【例】呈梯形输出二维数......
  • Java---数组
    学完之后需要实现这两个问题:#生成六个1-33之间的随机数,要求不重复+特殊号码(生成彩票)#数组扩容:先定义一个十个长度的数组,写一个方法用于向数组里面存值,每次只存入一个,反复的调用存值的这个方法,当存入的值超过十个以后,数组长度自动扩充用于存放后面的数据。创建数组本质上还......
  • MFC动态数组CArray
             ......
  • 【代码随想录算法训练营第二天】977.有序数组的平方、209.长度最小的子数组 、59.螺旋
    Day2-数组2023.9.15Leetcode977有序数组的平方给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。初解我还是不能想到暴力解法之外的,对某个问题的最优复杂度也没有概念。就算提示我是用指针,我也想不到思路。现在我知......
  • 二维数组最大连续和
    最大相连男生importjava.util.Scanner;importjava.util.*;//注意类名必须为Main,不要有任何packagexxx信息publicclassMain{staticintrow;staticintcol;staticint[][]arr;staticint[][]offsets={{0,1},{1,0},{1,-1},{1,1}};......