2021-04-04:给定一个非负数组arr,和一个正数m。 返回arr的所有子序列中累加和%m之后的最大值。
2021-04-04:给定一个非负数组arr,和一个正数m。 返回arr的所有子序列中累加和%m之后的最大值。
福大大 答案2021-04-04:
自然智慧即可。
1.递归,累加和。
2.动态规划,累加和。
3.动态规划,累加和%m。
4.双向动态规划,累加和%m。
代码用golang编写。代码如下:
package main
import (
"fmt"
"math/rand"
"sort"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
const TOTAL = 500
RightCount := 0
for i := 0; i < TOTAL; i++ {
arr := NewRandArr()
m := rand.Intn(200) + 1
fmt.Println(arr, m)
ret1 := max1(arr, m)
fmt.Println("1.递归,累加和:", ret1)
ret2 := max2(arr, m)
fmt.Println("2.动态规划,累加和:", ret2)
ret3 := max3(arr, m)
fmt.Println("3.动态规划,累加和%m:", ret3)
ret4 := max4(arr, m)
fmt.Println("4.双向动态规划,累加和%m:", ret4)
fmt.Println("---------------------")
if ret1 == ret2 && ret1 == ret3 && ret1 == ret4 {
RightCount++
}
}
fmt.Println("总数:", TOTAL)
fmt.Println("正确:", RightCount)
}
//递归,算出所有子序列的累加和
func max1(arr []int, m int) int {
set := make(map[int]struct{})
process(arr, 0, 0, set)
max := 0
for sum, _ := range set {
max = getMax(max, sum%m)
}
return max
}
func process(arr []int, index int, sum int, set map[int]struct{}) {
if index == len(arr) {
set[sum] = struct{}{}
} else {
process(arr, index+1, sum, set)
process(arr, index+1, sum+arr[index], set)
}
}
func getMax(a int, b int) int {
if a > b {
return a
} else {
return b
}
}
//2.动态规划,算出所有的累加和
func max2(arr []int, m int) int {
sum := 0
N := len(arr)
for i := 0; i < N; i++ {
sum += arr[i]
}
dp := make([][]bool, N)
for i := 0; i < N; i++ {
dp[i] = make([]bool, sum+1)
}
for i := 0; i < N; i++ {
dp[i][0] = true
}
dp[0][arr[0]] = true
for i := 1; i < N; i++ {
for j := 1; j <= sum; j++ {
dp[i][j] = dp[i-1][j]
if j-arr[i] >= 0 {
dp[i][j] = dp[i][j] || dp[i-1][j-arr[i]]
}
}
}
ans := 0
for j := 0; j <= sum; j++ {
if dp[N-1][j] {
ans = getMax(ans, j%m)
}
}
return ans
}
//3.动态规划,算出所有的模m的累加和。数组长度巨大,m不大。
func max3(arr []int, m int) int {
N := len(arr)
// 0...m-1
dp := make([][]bool, N)
for i := 0; i < N; i++ {
dp[i] = make([]bool, m)
}
for i := 0; i < N; i++ {
dp[i][0] = true
}
dp[0][arr[0]%m] = true
for i := 1; i < N; i++ {
for j := 1; j < m; j++ {
// dp[i][j] T or F
dp[i][j] = dp[i-1][j]
cur := arr[i] % m
if cur <= j {
dp[i][j] = dp[i][j] || dp[i-1][j-cur]
} else {
dp[i][j] = dp[i][j] || dp[i-1][m+j-cur]
}
}
}
ans := 0
for i := 0; i < m; i++ {
if dp[N-1][i] {
ans = i
}
}
return ans
}
// 如果arr的累加和很大,m也很大
// 但是arr的长度相对不大
func max4(arr []int, m int) int {
if len(arr) == 1 {
return arr[0] % m
}
mid := (len(arr) - 1) / 2
sortSet1 := make(map[int]struct{})
process4(arr, 0, 0, mid, m, sortSet1)
sortSet2 := make(map[int]struct{})
process4(arr, mid+1, 0, len(arr)-1, m, sortSet2)
ans := 0
s1 := make([]int, 0)
for key, _ := range sortSet1 {
s1 = append(s1, key)
}
sort.Ints(s1)
//fmt.Println("s1:", s1)
s2 := make([]int, 0)
for key, _ := range sortSet2 {
s2 = append(s2, key)
}
sort.Ints(s2)
//fmt.Println("s2:", s2)
for _, leftMod := range s1 {
//ans = getMax(ans, leftMod + sortSet2.floor(m - 1 - leftMod));
index := NearestIndex2(s2, m-1-leftMod)
if index >= 0 {
ans = getMax(ans, leftMod+s2[index])
} else {
ans = getMax(ans, leftMod)
}
}
return ans
}
// 在arr上,找满足<=value的最右位置
func NearestIndex2(arr []int, v int) int {
L := 0
R := len(arr) - 1
index := -1 // 记录最右的对号
for L <= R {
mid := L + (R-L)>>1
if arr[mid] <= v {
index = mid
L = mid + 1
} else {
R = mid - 1
}
}
return index
}
// 从index出发,最后有边界是end+1,arr[index...end]
func process4(arr []int, index int, sum int, end int, m int, sortSet map[int]struct{}) {
if index == end+1 {
sortSet[sum%m] = struct {
}{}
} else {
process4(arr, index+1, sum, end, m, sortSet)
process4(arr, index+1, sum+arr[index], end, m, sortSet)
}
}
func NewRandArr() []int {
arrLen := rand.Intn(10) + 5
arr := make([]int, arrLen)
for i := 0; i < arrLen; i++ {
arr[i] = rand.Intn(50)
}
return arr
}
执行结果如下:

2021-04-04:给定一个非负数组arr,和一个正数m。 返回arr的所有子序列中累加和%m之后的最大值。的更多相关文章
- 给一个非矩形数组(Nonrectangular Arrays)
Nonrectangular Arrays(非矩形数组) public class Test { public static void main(String[] args) { ...
- 给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
从第0行开始,输出第k行,传的参数为第几行,所以在方法中先将所传参数加1,然后将最后一行加入集合中返回. 代码如下: public static List<Integer> generat ...
- 提交一个变量或数组到另一个jsp页面
注意一:提交一个变量到另一个jsp页面,用hidden的input 另一个页面用request.getParameter();获取 注意二:提交一个数组到另一个页面,可以用相同的input的n ...
- 如何用一个for循环打印出一个二维数组
思路分析: 二维数组在内存中默认是按照行存储的,比如一个二维数组{{1,2,3,},{4,5,6}},它在内存中存储的顺序就是1.2.3.4.5.6,也就是说,对于这6个数组元素,按照从0到5给它们编 ...
- 给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 ,返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况)
""" #给定一个只包含正整数的非空数组,返回该数组中重复次数最多的前N个数字 #返回的结果按重复次数从多到少降序排列(N不存在取值非法的情况) 解题思路: 1.设定一个 ...
- 语义分割(semantic segmentation) 常用神经网络介绍对比-FCN SegNet U-net DeconvNet,语义分割,简单来说就是给定一张图片,对图片中的每一个像素点进行分类;目标检测只有两类,目标和非目标,就是在一张图片中找到并用box标注出所有的目标.
from:https://blog.csdn.net/u012931582/article/details/70314859 2017年04月21日 14:54:10 阅读数:4369 前言 在这里, ...
- [饭后算法系列] 数组中"和非负"的最长子数组
1. 问题 给定一列数字数组 a[n], 求这个数组中最长的 "和>=0" 的子数组. (注: "子数组"表示下标必须是连续的. 另一个概念"子 ...
- 2021.11.04 P1392 取数(多路归并)
2021.11.04 P1392 取数(多路归并) P1392 取数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 在一个n行m列的数阵中,你须在每一行取一个数(共n个数) ...
- NET的堆和栈04,对托管和非托管资源的垃圾回收以及内存分配
在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...
- Python算法每日一题--001--给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: 输入: [ ...
随机推荐
- AppScan的安装及破解1
(一)AppScan的安装及破解 IBM AppScan是一款目前最好用的Web 应用安全测试工具,Rational AppScan 可自动化 Web 应用的安全漏洞评估工作,能扫描和检测所有常见 ...
- 除select外查询数据的另一种姿势
1.24 1.[GYCTF2020]Blacklist buuctf上的题目 1.解题过程 输入1会返回一个数组,加上单引号就报错了,说明存在注入 以前做过类似的估计是堆叠注入,尝试一下 注入成功 正 ...
- 如何获取obs视频帧的二进制数据
前面几篇文章梳理了obs的录屏和推流流程,几条纵线整理下来,算是基本理清了obs的工作流程. 现在回到第一个目标:捕捉桌面的帧数据,用rendertarget显示并输出到UE5材质. 那么,帧数据到底 ...
- 【故障公告】数据库服务器 CPU 近 100% 造成全站故障,雪上加霜难上加难的三月
数据库服务器 CPU 近 100% 问题几乎每年都要发生一次,上次发生在去年1月31日,每次都是通过主备切换或者重启实例解决,数据库服务用的是阿里云 RDS SQL Server 2016 标准版. ...
- ML-程序练习-Dragon
回归问题 前期 假设已有某样例,参数为w=1.477, b=0.089,即为\(y=1.477x+0.089\) 过程分析 数据采样 首先我们需要模拟一些带有真实样本观测误差的数据(因为真实情况是真实 ...
- 一条SQL语句在MySQL中如何执行
一条SQL语句在MySQL中如何执行 本篇文章会分析一个 sql 语句在 MySQL 中的执行流程,包括 sql 的查询在 MySQL 内部会怎么流转,sql 语句的更新是怎么完成的. 在分析之前我会 ...
- 【深入浅出 Yarn 架构与实现】6-2 NodeManager 状态机管理
一.简介 NodeManager(NM)中的状态机分为三类:Application.Container 和 LocalizedResource,它们均直接或者间接参与维护一个应用程序的生命周期. 当 ...
- String API(全)
类型 名称 char charAt(int index)返回 char指定索引处的值. int codePointAt(int index)返回指定索引处的字符(Unicode代码点). int co ...
- Linux磁盘LVM根目录扩容
LVM 的基本概念 物理卷 Physical Volume (PV):可以在上面建立卷组的媒介,可以是硬盘分区,也可以是硬盘本身或者回环文件(loopback file).物理卷包括一个特殊的 hea ...
- 实现自定义注解,实现ioc与aop
实现自定义注解主要分三个步骤: 1.定义自己的注解类. 注解类默认继承Annotation接口. 且注解内的属性默认public(要给别人用的) 属性可以定义默认值也就是不给你的属性传值也会拥有默认. ...