首页 > 其他分享 >2023-12-20:用go语言,给定一个数组arr,长度为n,在其中要选两个不相交的子数组。 两个子数组的累加和都要是T,返回所有满足情况中,两个子数组长度之和最小是多少? 如果没有有效方法,返回-

2023-12-20:用go语言,给定一个数组arr,长度为n,在其中要选两个不相交的子数组。 两个子数组的累加和都要是T,返回所有满足情况中,两个子数组长度之和最小是多少? 如果没有有效方法,返回-

时间:2023-12-20 18:02:21浏览次数:39  
标签:返回 arr return int sum 数组 ans 长度

2023-12-20:用go语言,给定一个数组arr,长度为n,在其中要选两个不相交的子数组。

两个子数组的累加和都要是T,返回所有满足情况中,两个子数组长度之和最小是多少?

如果没有有效方法,返回-1。

正式 :

2 <= n <= 10^6

0 <= arr[i] <= 10000

1 <= T <= 10^8

扩展 :

2 <= n <= 10^6

-10000 <= arr[i] <= 10000

1 <= T <= 10^8

都能时间复杂度做到O(N)。

来自字节。

答案2023-12-20:

来自左程云

灵捷3.5

大体步骤如下:

Algorithm 1: minLenBothT1

1.初始化数组arr的累加和数组sum,并计算arr的累加和。

2.初始化变量ans为一个较大的整数。

3.使用四重循环遍历所有可能的起始和结束索引组合(a, b, c, d)。

4.检查子数组[a, b]和[c, d]的累加和是否等于目标值T。

5.如果满足条件,则更新ans为两个子数组长度之和的最小值。

6.如果ans的值没有被更新过,则返回-1,否则返回ans。

Algorithm 2: minLenBothT2

1.初始化变量ans为一个较大的整数。

2.遍历数组arr,寻找和为0的连续子数组,记录其长度为cnt。

3.如果cnt大于等于2,则返回2作为结果。

4.对于每个起始索引l,从右侧扩展子数组的结束索引r,使得子数组的和尽量接近目标值T。

5.记录满足和为T的子数组的最小长度到right[l]数组中。

6.从右到左遍历数组arr,对于每个结束索引r,从左侧缩小子数组的起始索引l,使得子数组的和尽量接近目标值T。

7.如果和为T且right[r+1]不是无穷大,则更新ans为当前长度+r-l+right[r+1]的最小值。

8.如果ans的值没有被更新过,则返回-1,否则返回ans。

Algorithm 3: minLenBothT3

1.初始化变量ans为一个较大的整数。

2.构建累加和出现次数的映射表sums,初始时将0的索引设置为-1。

3.构建左侧最小长度的数组left,初始时将所有元素设置为一个较大的整数。

4.遍历数组arr,计算累加和sum,并检查sum-t在sums中是否存在。

5.如果存在,则更新左侧最小长度left[i]为当前索引i与sums[sum-t]之差。

6.更新sums[sum]为当前索引i。

7.从左到右遍历left数组,将每个位置的值更新为其与前一个位置的较小值。

8.清空sums映射表,并将0的索引设置为数组arr的长度。

9.从右到左遍历数组arr,计算累加和sum,并检查sum-t在sums中是否存在且左侧最小长度left[i-1]不是一个较大的整数。

10.如果满足条件,则更新ans为当前长度+sums[sum-t]-i的最小值。

11.更新sums[sum]为当前索引i。

12.如果ans的值没有被更新过,则返回-1,否则返回ans。

Algorithm 1:

  • 时间复杂度:O(n^4)
  • 空间复杂度:O(n)

Algorithm 2:

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

Algorithm 3:

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

go语言完整代码如下:

package main

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

func minLenBothT1(arr []int, t int) int {
	n := len(arr)
	sum := make([]int, n)
	sum[0] = arr[0]
	for i := 1; i < n; i++ {
		sum[i] = sum[i-1] + arr[i]
	}
	ans := math.MaxInt32
	for a := 0; a < n-1; a++ {
		for b := a; b < n-1; b++ {
			for c := b + 1; c < n; c++ {
				for d := c; d < n; d++ {
					if sum1(a, b, sum) == t && sum1(c, d, sum) == t {
						ans = min(ans, b+d-a-c+2)
					}
				}
			}
		}
	}
	if ans == math.MaxInt32 {
		return -1
	}
	return ans
}

func sum1(l, r int, sum []int) int {
	if l == 0 {
		return sum[r]
	}
	return sum[r] - sum[l-1]
}

func minLenBothT2(arr []int, t int) int {
	n := len(arr)
	if t < 0 {
		return -1
	}
	if t == 0 {
		cnt := 0
		for _, num := range arr {
			if num == 0 {
				cnt++
			}
		}
		if cnt >= 2 {
			return 2
		}
		return -1
	}
	right := make([]int, n)
	for i := 0; i < n; i++ {
		right[i] = math.MaxInt32
	}
	for l, r, sum := 1, 1, 0; l < n; l++ {
		r = max(r, l)
		for r < n && sum < t {
			sum += arr[r]
			r++
		}
		if sum == t {
			right[l] = r - l
		}
		sum -= arr[l]
	}
	for i := n - 2; i >= 0; i-- {
		right[i] = min(right[i], right[i+1])
	}
	ans := math.MaxInt32
	for r, l, sum := n-2, n-2, 0; r >= 0; r-- {
		l = min(l, r)
		for l >= 0 && sum < t {
			sum += arr[l]
			l--
		}
		if sum == t && right[r+1] != math.MaxInt32 {
			ans = min(ans, r-l+right[r+1])
		}
		sum -= arr[r]
	}
	if ans == math.MaxInt32 {
		return -1
	}
	return ans
}

func minLenBothT3(arr []int, t int) int {
	n := len(arr)
	sums := make(map[int]int)
	sums[0] = -1
	left := make([]int, n)
	for i := 0; i < n; i++ {
		left[i] = math.MaxInt32
	}
	for i, sum := 0, 0; i < n-1; i++ {
		sum += arr[i]
		if l, found := sums[sum-t]; found {
			left[i] = i - l
		}
		sums[sum] = i
	}
	for i := 1; i < n-1; i++ {
		left[i] = min(left[i-1], left[i])
	}
	ans := math.MaxInt32
	sums = make(map[int]int)
	sums[0] = n
	for i, sum := n-1, 0; i >= 1; i-- {
		sum += arr[i]
		if _, found := sums[sum-t]; found && left[i-1] != math.MaxInt32 {
			ans = min(ans, left[i-1]+sums[sum-t]-i)
		}
		sums[sum] = i
	}
	if ans == math.MaxInt32 {
		return -1
	}
	return ans
}

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

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

func randomArray1(n, v int) []int {
	arr := make([]int, n)
	for i := 0; i < n; i++ {
		arr[i] = rand.Intn(v + 1)
	}
	return arr
}

func randomArray2(n, v int) []int {
	arr := make([]int, n)
	for i := 0; i < n; i++ {
		arr[i] = rand.Intn(2*v+1) - v
	}
	return arr
}

func main() {
	rand.Seed(time.Now().UnixMicro())
	N := 100
	V := 100
	T := 100
	testTimes := 10000
	fmt.Println("正式方法测试开始")
	for i := 0; i < testTimes; i++ {
		n := rand.Intn(N) + 2
		v := rand.Intn(V) + 1
		arr := randomArray1(n, v)
		t := rand.Intn(T)
		ans1 := minLenBothT1(arr, t)
		ans2 := minLenBothT2(arr, t)
		if ans1 != ans2 {
			fmt.Println("出错了!")
		}
	}
	fmt.Println("正式方法测试结束")

	fmt.Println("扩展方法测试开始")
	for i := 0; i < testTimes; i++ {
		n := rand.Intn(N) + 2
		v := rand.Intn(V) + 1
		arr := randomArray2(n, v)
		t := rand.Intn(T)
		ans1 := minLenBothT1(arr, t)
		ans3 := minLenBothT3(arr, t)
		if ans1 != ans3 {
			fmt.Println("出错了!")
		}
	}
	fmt.Println("扩展方法测试结束")
}

2023-12-20:用go语言,给定一个数组arr,长度为n,在其中要选两个不相交的子数组。 两个子数组的累加和都要是T,返回所有满足情况中,两个子数组长度之和最小是多少? 如果没有有效方法,返回-_子数组

标签:返回,arr,return,int,sum,数组,ans,长度
From: https://blog.51cto.com/moonfdd/8909735

相关文章

  • 2023-12-20:用go语言,给定一个数组arr,长度为n,在其中要选两个不相交的子数组。 两个子数
    2023-12-20:用go语言,给定一个数组arr,长度为n,在其中要选两个不相交的子数组。两个子数组的累加和都要是T,返回所有满足情况中,两个子数组长度之和最小是多少?如果没有有效方法,返回-1。正式:2<=n<=10^60<=arr[i]<=100001<=T<=10^8扩展:2<=n<=10^6-10000<=a......
  • Task基础-创建Task,Task传参,获取Task返回值
    Task基础-创建Task,Task传参,获取Task返回值Task基础介绍Task的创建获取Task的执行结果 补充细节1、Task基础介绍Task类是TaskProgrammingLibrary(TPL)中最核心的一个类,下面我将会像大家展示如何使用一些方法来创建不同类型的Task,取消Task,等待Task执行完成,获取Task执行......
  • c语言 数组与指针
    @TOC前言之前我们讲了指针数组,今天讲一下数组指针。一、数组与指针的概述:数组指针就是数组的指针,就是指向数组的指针。inta[5]={1,2,3,4,5};//定义一个数组int*p=&a[0];//定义一个指针指向数组的首地址,由于数组的首地址就是数组名,所以&a[0]==a;则可写为int*......
  • [LeetCode] LeetCode81. 搜索旋转排序数组II
    题目描述思路:是lc33.搜索旋转排序数组的延伸,允许包含重复元素起初:当nums[left]<=nums[mid]时,区间[left,mid]有序当nums[left]>nums[mid]时,区间[mid,right]有序但是这个题目当nums[left]==nums[mid]时,无法判断哪个区间是有序的,无法判断target位于左侧还是右侧,此时无......
  • [LeetCode Hot 100] LeetCode153. 寻找旋转排序数组中的最小值
    题目描述思路如果数组翻转后又回到升序的情况,即nums[left]<=nums[right],则nums[left]就是最小值,直接返回。如果数组翻转,需要找到数组中第二部分的第一个元素:若nums[left]<=nums[mid],说明区间[left,mid]连续递增,则最小元素一定不在这个区间里,可以直接排除,最小值在[......
  • 912. 排序数组---快速排序
    1.题目介绍给你一个整数数组 \(nums\),请你将该数组升序排列。示例1:输入:nums=[5,2,3,1]输出:[1,2,3,5]示例2:输入:nums=[5,1,1,2,0,0]输出:[0,0,1,1,2,5]提示:\(1<=nums.length<=5*10^{4}\)\(-5*10^{4}<=nums[i]<=5*10^{4}\)2.题解2.1随机化快速排......
  • 深度解析ArrayList:灵活高效的动态数组实现
    在Java集合框架中,ArrayList是一个常用而强大的类,它提供了动态数组的实现,允许在运行时动态调整数组的大小。ArrayList是List接口的实现类,基于动态数组的数据结构。它可以存储任意类型的对象,并提供了丰富的方法,包括添加、删除、遍历等,使其在各种场景下都能发挥重要作用。底层......
  • js 处理对象数组 + map 筛选出指定字段数据 + filter过滤重复数据/指定数据
    constres=[{id:1,name:'zhangsan',age:16,gender:0},{id:1,name:'zhangsan',age:16,gender:0},{id:2,name:'lisi',age:20,gender:1}];获取res中的id和name/*[{"id&......
  • 两个数组的过滤
    leta1=[{rmName:'王五'},{rmName:'李四'},{rmName:'张三'},{rmName:'赵六'}];letb2=[{name:'王五'},{name:'李四'}];//结果:得到a1中除去b2中值的其他数据//方法一:forEachletfilterA1=a1.filter(item=>......
  • 算法数组集合
    JDK1.0java.util.Date缺陷:偏移量JDK1.1java.util.Calendar线程不安全缺陷:a.偏移量b.可变性,线程不安全的c.格式化:java.text.DateFormat只适用于Date,不能用于CalendarJDK8.0java.time:时间包LocalDate:只有年月日LocalTime:只有时分秒L......