首页 > 其他分享 >2023-12-09:用go语言,给你两个整数数组 arr1 和 arr2, 返回使 arr1 严格递增所需要的最小「操作」数(可能为 0)。 每一步「操作」中,你可以分别从 arr1 和 arr2

2023-12-09:用go语言,给你两个整数数组 arr1 和 arr2, 返回使 arr1 严格递增所需要的最小「操作」数(可能为 0)。 每一步「操作」中,你可以分别从 arr1 和 arr2

时间:2023-12-09 17:34:29浏览次数:41  
标签:12 cur int arr2 arr1 ans dp

2023-12-09:用go语言,给你两个整数数组 arr1 和 arr2,

返回使 arr1 严格递增所需要的最小「操作」数(可能为 0)。

每一步「操作」中,你可以分别从 arr1 和 arr2 中各选出一个索引,

分别为 i 和 j,0 <= i < arr1.length 和 0 <= j < arr2.length,

然后进行赋值运算 arr1[i] = arr2[j]。如果无法让 arr1 严格递增,请返回 -1。

输入:arr1 = [1,5,3,6,7], arr2 = [4,3,1]。

输出:2。

答案2023-12-09:

灵捷3.5

大体过程如下:

算法1(makeArrayIncreasing1):

1.对arr2进行排序并去除重复元素,生成新的数组help,并统计cnt为help的长度。

2.通过递归函数process1来计算从arr1的索引i开始到结尾的最小操作数。初始时,i为-1。

3.在process1中,通过二分查找函数find,在arr2中找到第一个大于cur的元素的索引f。

4.使用循环遍历arr1中从i+1到末尾的元素。

  • 若当前元素大于cur,则说明可以选择该元素,继续递归调用process1,并将操作数times加1。

  • 若f不等于-1且小于arr2的长度,更新cur为arr2[f],同时f加1,times加1。

  • 若f等于-1或大于等于arr2的长度,跳出循环。

5.返回递归调用的结果ans,即最小操作数。

算法2(makeArrayIncreasing2):

1.对arr2进行排序并去除重复元素,生成新的数组help,并统计cnt为help的长度。

2.创建dp数组,初始值为-1。

3.通过递归函数process2来计算从arr1的索引i开始到结尾的最小操作数。同时,使用dp数组记录已计算过的结果,以便后续查询。

4.在process2中,若dp[i+1]不等于-1,直接返回dp[i+1]。

5.剩下的过程与makeArrayIncreasing1基本相同,只是将递归调用替换为对dp数组的查询和更新。

6.返回递归调用的结果ans,同时将其保存到dp[i+1]中。

算法3(makeArrayIncreasing3):

1.对arr2进行排序并去除重复元素,生成新的数组arr2,并统计m为arr2的长度。

2.创建dp数组,长度为n+2,并初始化为最大整数。

3.从arr1末尾向前遍历,使用循环计算从索引i开始到结尾的最小操作数。

  • 初始化cur为arr1[i],f为在arr2中找到第一个大于cur的元素的索引。

  • 初始化dp[i+1]为最大整数,times为0。

  • 使用循环遍历arr1中从i+1到末尾的元素,操作步骤与makeArrayIncreasing1和makeArrayIncreasing2相似。

  • 若dp[j+1]不等于最大整数,更新dp[i+1]为times+dp[j+1]与dp[i+1]中的较小值。

  • 若f不等于-1且小于m,更新cur为arr2[f],同时f加1,times加1。

  • 若f等于-1或大于等于m,跳出循环。

4.若dp[0]等于最大整数,返回-1;否则返回dp[0]作为最小操作数。

时间复杂度分析:

  • 算法1和算法2的时间复杂度为O(n * m),其中n和m分别为arr1和arr2的长度,因为每个元素都需要遍历一次。

  • 算法3的时间复杂度为O(n * m + m * log(m)),其中m为arr2的长度,因为要对arr2进行排序并进行二分查找。

额外空间复杂度分析:

  • 算法1和算法2的额外空间复杂度为O(m),用于存储去重后的arr2。

  • 算法3的额外空间复杂度为O(m),用于存储去重后的arr2,并且使用了一个大小为n+2的dp数组来记录中间结果。

go完整代码如下:

package main

import (
	"fmt"
	"math"
	"sort"
)

func makeArrayIncreasing1(arr1 []int, arr2 []int) int {
	sort.Ints(arr2)
	cnt := 1
	for i := 1; i < len(arr2); i++ {
		if arr2[i] != arr2[i-1] {
			cnt++
		}
	}
	help := make([]int, cnt)
	help[0] = arr2[0]
	for i, j := 1, 1; i < len(arr2); i++ {
		if arr2[i] != arr2[i-1] {
			help[j] = arr2[i]
			j++
		}
	}
	ans := process1(arr1, help, -1)
	if ans == math.MaxInt64 {
		return -1
	}
	return ans
}

func process1(arr1 []int, arr2 []int, i int) int {
	if i == len(arr1) {
		return 0
	} else {
		cur := 0
		if i == -1 {
			cur = math.MinInt64
		} else {
			cur = arr1[i]
		}
		f := find(arr2, cur)
		ans := math.MaxInt64
		times := 0
		for j := i + 1; j <= len(arr1); j++ {
			if j == len(arr1) || cur < arr1[j] {
				next := process1(arr1, arr2, j)
				if next != math.MaxInt64 {
					ans = min(ans, times+next)
				}
			}
			if f != -1 && f < len(arr2) {
				cur = arr2[f]
				f++
				times++
			} else {
				break
			}
		}
		return ans
	}
}

func find(arr2 []int, num int) int {
	l := 0
	r := len(arr2) - 1
	ans := -1
	for l <= r {
		m := (l + r) / 2
		if arr2[m] > num {
			ans = m
			r = m - 1
		} else {
			l = m + 1
		}
	}
	return ans
}

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

func makeArrayIncreasing2(arr1 []int, arr2 []int) int {
	sort.Ints(arr2)
	cnt := 1
	for i := 1; i < len(arr2); i++ {
		if arr2[i] != arr2[i-1] {
			cnt++
		}
	}
	help := make([]int, cnt)
	help[0] = arr2[0]
	for i, j := 1, 1; i < len(arr2); i++ {
		if arr2[i] != arr2[i-1] {
			help[j] = arr2[i]
			j++
		}
	}
	dp := make([]int, len(arr1)+1)
	for i := range dp {
		dp[i] = -1
	}
	ans := process2(arr1, help, -1, dp)
	if ans == math.MaxInt64 {
		return -1
	}
	return ans
}

func process2(arr1 []int, arr2 []int, i int, dp []int) int {
	if i == len(arr1) {
		return 0
	} else {
		if dp[i+1] != -1 {
			return dp[i+1]
		}
		cur := 0
		if i == -1 {
			cur = math.MinInt64
		} else {
			cur = arr1[i]
		}
		f := find(arr2, cur)
		ans := math.MaxInt64
		times := 0
		for j := i + 1; j <= len(arr1); j++ {
			if j == len(arr1) || cur < arr1[j] {
				next := process2(arr1, arr2, j, dp)
				if next != math.MaxInt64 {
					ans = min(ans, times+next)
				}
			}
			if f != -1 && f < len(arr2) {
				cur = arr2[f]
				f++
				times++
			} else {
				break
			}
		}
		dp[i+1] = ans
		return ans
	}
}

func makeArrayIncreasing3(arr1 []int, arr2 []int) int {
	sort.Ints(arr2)
	m := 1
	for i := 1; i < len(arr2); i++ {
		if arr2[i] != arr2[m-1] {
			arr2[m] = arr2[i]
			m++
		}
	}
	n := len(arr1)
	dp := make([]int, n+2)
	for i := n - 1; i >= -1; i-- {
		cur := 0
		if i == -1 {
			cur = math.MinInt64
		} else {
			cur = arr1[i]
		}
		f := find3(arr2, m, cur)
		dp[i+1] = math.MaxInt64
		times := 0
		for j := i + 1; j <= n; j++ {
			if j == n || cur < arr1[j] {
				if dp[j+1] != math.MaxInt64 {
					dp[i+1] = min(dp[i+1], times+dp[j+1])
				}
			}
			if f != -1 && f < m {
				cur = arr2[f]
				f++
				times++
			} else {
				break
			}
		}
	}
	if dp[0] == int(^uint(0)>>1) {
		return -1
	}
	return dp[0]
}

func find3(arr2 []int, size int, num int) int {
	l := 0
	r := size - 1
	ans := -1
	for l <= r {
		m := (l + r) / 2
		if arr2[m] > num {
			ans = m
			r = m - 1
		} else {
			l = m + 1
		}
	}
	return ans
}

func main() {
	if true {
		arr1 := []int{1, 5, 3, 6, 7}
		arr2 := []int{4, 3, 1}
		fmt.Println(makeArrayIncreasing1(arr1, arr2))
	}
	if true {
		arr1 := []int{1, 5, 3, 6, 7}
		arr2 := []int{4, 3, 1}
		fmt.Println(makeArrayIncreasing2(arr1, arr2))
	}
	if true {
		arr1 := []int{1, 5, 3, 6, 7}
		arr2 := []int{4, 3, 1}
		fmt.Println(makeArrayIncreasing3(arr1, arr2))
	}
}

在这里插入图片描述

标签:12,cur,int,arr2,arr1,ans,dp
From: https://www.cnblogs.com/moonfdd/p/17891214.html

相关文章

  • 模拟套题 12.9
    不敢想象这是曾经初二的人做的T1非皇后大意:给定\(R\)行\(C\)列的棋盘你可以随便在一个格子放一个非皇后要求不能走直线和对角线走\(M\)步将走过的格子按顺序记起来求最终有多少种不同排列Solutiondp裸题定义\(f_{i,j,k}\)为走了\(i\)次,到格子\((j,k)\)......
  • 7. 2023-11-20 12:29:32,542 [tornado.general :456 ][WARNING ][3052] Got events f
     这个警告表明Tornado检测到了有事件(events)被发送到一个已经关闭的流(stream)。在Tornado中,一个流代表一个请求或响应的数据流。这个警告可能意味着在请求处理的过程中,尝试向已经关闭的流发送了事件。可能的原因和解决方法:异步操作处理不当:在Tornado中,当你处理异步请求时,需......
  • 2023-12
    2023-12*UcupStage11:NaningD.RedBlackTree(QOJ7736)好题。Description给你一颗树,每个节点有一个颜色(红或黑),定义一棵树是好的指这棵树中的所有节点到他子树中的叶子节点路径上的黑色节点数都相等。对每个\(1\lei\len\),求要使以\(i\)为子树是好的,至少要改变多少......
  • CentOS 7.6 安装 Go 1.20.12 环境教程+更换国内源
    安装因为需要安装httpx,官方github要求使用1.20版本的Go环境,就没有安装最新的1.21。先去官网查看:https://go.dev/dl/如上图,我们选择Linuxamd64的(使用命令下就行,如若不能正常下载,就直接下完传上服务器也一样)wgethttps://go.dev/dl/go1.20.12.linux-amd64.tar.gz2.其次......
  • 1209考试总结
    只打暴力能得240分的比赛。题目链接A.火柴棍打一个\(n\leq40\)的暴搜可以发现规律:\(ans_i=ans_{i-7}\times10+8\)。显然有f[]={0,1,7,4,2,0,8,10,18,22,20,28,68,88,108,188,200,208,288,688}。然后就没了。考场选择自信打表。然后Lemon代码长度限制50KB。挂完。......
  • 12.09
    今天利用上午时间完成了.netc#的实验四编写一个简易的文件管理器,通过本次实验,练习TreeView、ListView和SplitContainer控件的使用,同时熟悉C#文件系统的操作方法以及File类和Directory类的使用。 通过Windows窗体应用程序,实现了一个简单的文件浏览器界面。界面分为左右......
  • 2012年12月 英语四级
    PartⅤWriting写作提示:本文要求写一封贷款信。理由要充分,对学生来说,由于家庭困难而无法支付学费是不错的话题。在行文时需注意句子结构的变化,简单句、并列句和复杂句尽可能交叉使用。在涉及词语的使用时,注意有意识的变化,比如“主修”可以表述为“majorin”或“specializein”......
  • 2023.12
    启动。DEGwer'sDoctoralDissertationCheeringContest好魔怔的比赛。E.HalfPalindromes先考虑单个\(f(l,r)\)的计算,有结论:我们一定会不断删最小的长度为\(k\)的前缀,满足前\(2k+1\)个字符是回文的。直到没有这样的\(k\)为止。证明也很容易,假设我们某一步删了长度......
  • 20231209
    我还活着。早上一起来就绷不住了。我昨天收拾塑形镜的用具的时候忘了把护理液拿回来。昨晚我给家长说了,然后家长说没有就不用了呗。然后今天早上我就没用。我妈拿着一个没开封的护理液(外面的盒子都没拆)问我我用了吗。(这算是明知故问吗?)我疑惑了,我说我没用,我不知道啊。我妈......
  • 12.9 蓝桥杯 huffuman树c语言
    今天学习了蓝桥杯的huffuman树,总结如下:问题描述Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。给出一列数{pi}={p0,p1,…,pn-1},用这列数构造Huffman树的过程如下:1.找到{pi}中最小的两个数,设为pa和pb,将pa和pb从{pi}中删除掉,然后将它们的和加......