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: 输入: [ ...
随机推荐
- Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.1:test (default-test) on
解决错误 Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.1:test (default-test ...
- Python学习笔记W1
今天正式开始学习Python语言,学习方式观看教学视频,完成作业.视频共计28周,争取每天2天完成一周教学内容,共计56天,预计完成日期:2019-2-28. Owen写于2018-12-22 ...
- rename基本操作
电脑是Macbook, 用Homebrew先安装rename. 如果没安装Homebrew 直接复制到terminal中回车, 时间稍长. ruby -e "$(curl -fsSL htt ...
- Android笔记--案例:登录界面以及登录逻辑
登录界面的实现 就是说,界面的绘制,并没有什么难度,只要控制好空间的分配就可以了 登录的逻辑实现 获取验证码.忘记密码的界面跳转.登录的实现: 确认文本框的输入内容是否符合题意:
- 关于wx.panel中添加wx.button按钮无显示问题记录
本次出现按钮不显示的原因为pos坐标理解出错: 1.按钮之所没有出现,是因为将全局坐标作为按钮pos的定位,导致在有限的panel布局内无法显示出按钮: 2.经过调试发现当pos=(-1,-1)时,按 ...
- .Net7 GC标记阶段代码的改变
前言 由于业务需求,在探究.Net7的CLR,发现了一个不通的地方,也就是通过GCInfo获取到了对象之后.它并没有在GcScanRoots(对象扫描标记)里面对它进行标记,那么如果没有标记这个对象如 ...
- 人脸关键点的应用场景及重难点解析丨Dev for Dev 专栏
本文为「Dev for Dev 专栏」系列内容,作者为声网视频组 AI 算法工程师 周世付. 人脸检测.人脸关键点检测,是计算机视觉的基础算法.许多酷炫应用背后,例如美颜.贴纸.人脸驱动 avatar ...
- Docker常用软件安装
jdk dockere pull openjdk:11 docker run -d -t --name java-11 openjdk:11 MySQL 可以从docker hup中查找自己想要安装的 ...
- 手动实现一个call bind
一.call的实现(apply类似) //完成版 Function.prototype.setCall = function (obj){ var object = obj || window let ...
- 集合-LinkedList 源码分析(JDK 1.8)
1.概述 LinkedList 是 Java 集合框架中一个重要的实现,其底层采用的双向链表结构.和 ArrayList 一样,LinkedList 也支持空值和重复值.由于 LinkedList 基 ...