2023-11-25:用 go 语言,给定一个数组 arr,长度为 n,表示 n 个格子的分数,并且这些格子首尾相连, 孩子不能选相邻的格子,不能回头选,不能选超过一圈, 但是孩子可以决定从任何位置开始选,也可以
2023-11-25:用 go 语言,给定一个数组 arr,长度为 n,表示 n 个格子的分数,并且这些格子首尾相连,
孩子不能选相邻的格子,不能回头选,不能选超过一圈,
但是孩子可以决定从任何位置开始选,也可以什么都不选。
返回孩子能获得的最大分值。
1 <= n <= 10^6,
0 <= arr[i] <= 10^6。
来自华为 od。
来自左程云。
答案 2023-11-25:
go 和 c++的代码用灵捷 3.5 编写,感觉有点抽风了,生成的代码需要修改才能运行。
大体过程如下:
1.暴力方法(max1 函数)
这种方法是一种递归的方式,通过尝试所有可能的组合来找到最大分值。
定义 max1 函数,接受一个长度为 n 的数组 arr 作为参数。
若 arr 的长度为 1,直接返回 arr[]作为结果。
否则,调用 process 函数,传入 arr、起始索引和一个长度为 n 的布尔类型数组 path(用于记录选择的路径)。
在 process 函数中,先检查是否已经遍历到数组末尾,若是,则判断首尾是否相连,如果是则返回最小整数值 math.MinInt32,否则遍历整个数组检查相邻格子是否被选中,如果有返回最小整数值。
初始化 ans 为,遍历数组,如果 path[j]为 true,则将 arr[j]加到 ans 上。
返回 ans 作为结果。
2.记忆化搜索(max2 函数)
这种方法使用动态规划的思想,借助一个二维数组 dp 来存储已计算的结果,以减少重复计算。
定义 max2 函数,接受一个长度为 n 的数组 arr 作为参数。
若 arr 的长度为 1,直接返回 arr[]作为结果。
否则,初始化 n 为 arr 的长度,并创建一个二维数组 dp,大小为[n][4],并将其所有元素设置为最小整数值 math.MinInt32。
初始化 ans 为 arr[]加上调用 process2 函数的结果,传入 arr、起始索引 1、、和 dp。
将 ans 更新为 ans 与调用 process2 函数,传入 arr、起始索引 1、、和 dp 的结果中的较大值。
返回 ans 作为结果。
3.正式方法(max3 函数)
这种方法是一种严格位置依赖的动态规划方法,同时使用空间压缩技巧,减少额外空间的使用。
定义 max3 函数,接受一个长度为 n 的数组 arr 作为参数。
若 arr 的长度为 1,直接返回 arr[]作为结果。
否则,初始化 n 为 arr 的长度,并创建两个大小为 4 的一维数组 next 和 cur,用于保存计算过程中的结果。
将 next[]初始化为 arr[n-1]的最大值和的较大值(即取和 arr[n-1]的较大值)。
从 n-2 开始向前遍历数组 arr,进行动态规划计算。
在每次遍历中,使用三重嵌套循环,遍历 pre 和 end,计算 cur[(pre<<1)|end]的值,其中<<为位运算符,|为按位或运算符。
更新 next 数组的值为 cur 数组的值。
最终,返回 arr[]+next[3]和 next[]中的较大值作为结果。
总结时间复杂度和空间复杂度:
第一种暴力方法的时间复杂度为 O(2^n),空间复杂度为 O(n)。
第二种记忆化搜索的时间复杂度为 O(n),空间复杂度为 O(n)。
第三种正式方法的时间复杂度为 O(n),空间复杂度为 O(1)。
go 完整代码如下:
c++完整代码如下:
版权声明: 本文为 InfoQ 作者【福大大架构师每日一题】的原创文章。
原文链接:【http://xie.infoq.cn/article/6cd5f847c104043422fd35146】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论