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,返回所有满足情况中,两个子数组长度之和最小是多少? 如果没有有效方法,返回-的更多相关文章

  1. 给定一个递增序列,a1 <a2 <...<an 。定义这个序列的最大间隔为d=max{ai+1 - ai }(1≤i<n),现在要从a2 ,a3 ..an-1 中删除一个元素。问剩余序列的最大间隔最小是多少?

    // ConsoleApplication5.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<vector> ...

  2. jquery ajax中支持哪些返回类型以及js中判断一个类型常用的方法?

    1 jquery ajax中支持哪些返回类型在JQuery中,AJAX有三种实现方式:$.ajax() , $.post , $.get(). 预期服务器返回的数据类型.如果不指定,jQuery 将自 ...

  3. EF Core 中DbContext不会跟踪聚合方法和Join方法返回的结果,及FromSql方法使用讲解

    EF Core中: 如果调用Queryable.Count等聚合方法,不会导致DbContext跟踪(track)任何实体. 此外调用Queryable.Join方法返回的匿名类型也不会被DbCont ...

  4. 了解PHP中的Array数组和foreach

    1. 了解数组 PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.详细的解释可参见:PHP.net中的Array数组    . 2.例子:一般的数组 这里,我 ...

  5. Spring MVC的方法返回值和参数传递

    1. SpringMVC方法的返回值类型 3.1String类作为返回值 3.1.1Controller层 /** * 返回值类型为String时,一般用于返回视图名称 * 1.当方法返回值为null ...

  6. 给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 ,返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况)

    """ #给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 #返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况) 解题思路: 1.设定一个 ...

  7. 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。

    /** * 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标. * * 你可以假设每种输入只会对应一个答案.但是,数组中 ...

  8. Gym 101064 D Black Hills golden jewels 【二分套二分/给定一个序列,从序列中任意取两个数形成一个和,两个数不可相同,要求求出第k小的组合】

    D. Black Hills golden jewels time limit per test 2 seconds memory limit per test 256 megabytes input ...

  9. 求数组中两两相加等于20的组合(Python实现)

    题目 求数组中两两相加等于20的组合. 例:给定一个数组[1, 7, 17, 2, 6, 3, 14],这个数组中满足条件的有两对:17+3=20, 6+14=20. 解析 分为两个步骤: 先采用堆排 ...

  10. 刷题之给定一个整数数组 nums 和一个目标值 taget,请你在该数组中找出和为目标值的那 两个 整数

    今天下午,看了一会github,想刷个题呢,就翻出来了刷点题提高自己的实际中的解决问题的能力,在面试的过程中,我们发现,其实很多时候,面试官 给我们的题,其实也是有一定的随机性的,所以我们要多刷更多的 ...

随机推荐

  1. HDLbits_Conwaylife

    题目介绍 题目链接 Conwaylife 简介 题目要求我们实现一个康威生命游戏的电路. 该游戏在一个二维网格空间中进行,在该题目中是 16 * 16 的大小,每一个格子都有两种状态(0 或 1),代 ...

  2. 上位机使用JS SerialPort进行串口通信, 包含开发环境搭建和完整示例代码

    在嵌入式开发中,我们经常需要使用上位机(PC)与一些电路模块进行通信, 用于获取一些传感器的数据,或者发送命令控制相应的电路模块.NodeJS目前支持使用SerialPort模块进行串口通信,本文主要 ...

  3. Solution -「营业」「CF 527C」Glass Carving

    Description Link. 有一个块 \(n\times m\) 的矩形,有 \(q\) 次操作,每次把矩形横 / 竖着切一刀,问切完后的最大矩形面积. Solution 一个不同于大多数人. ...

  4. 前端框架——Vue2

    文章目录 初识Vue 模板语法 数据绑定 el与data的两种写法 理解MVVM 数据代理 事件处理 计算属性 监视属性 绑定样式 条件渲染 列表渲染 收集表单数据 过滤器 内置指令 自定义指令 生命 ...

  5. ChatGPT API Transition Guide

    ChatGPT API Transition Guide How to get started Written by Joshua J.. Updated over a week ago Prompt ...

  6. Rust WebAssembly 绑定输入类型(基于 Serde)

    前言 单位有个项目要共享前后端检查策略后端用的正好也是 Rust,但是 Rust 默认的 wasm-bindgen 包中提供的转换操作非常少,像 Vec<T> <=> Arra ...

  7. 4款.NET开源的Redis客户端驱动库

    前言 今天给大家推荐4款.NET开源免费的Redis客户端驱动库(以下排名不分先后). Redis是什么? Redis全称是REmote DIctionary Service,即远程字典服务.Redi ...

  8. 当scroll-view水平滚动,内容溢出时,文本会自动竖向排列问题

    当scroll-view水平滚动,内容溢出时,文本会自动竖向排列 解决方法:thite-space:nowrap:规定段落中的文本不进行换行

  9. Vue之for循环

    Vue中for循环的用法总结如下: 1.基本用法 v-for <!DOCTYPE html> <html lang="en"> <head> & ...

  10. mysql之简单的多表查询

    最简单的多表查询需要用到连操作符(join) 1.笛卡儿积 形式为table1 join table2.如: select e.fname,e.lname,d.name from employee e ...