数组子序列累加和求余数之后的最大值问题详解

本文详细解析了如何求解数组arr的所有子序列累加和对正数m取余后的最大值问题。针对不同情况,如数组元素较小、m值小或元素大、m大等,提出暴力解法、背包解法和动态规划优化解法。通过动态规划的状态转移方程,以及二分查找等方法,降低时间复杂度,提高算法效率。
摘要由CSDN通过智能技术生成

给定一个非负的数组arr,和一个正数m,返回arr中所有子序列累加和对m求余数之后的最大值

1.如果arr中每个数字不大,怎么做这道题?
2.如果arr中m的值很小,怎么做这道题?
3.如果arr的长度很短,但是每个arr中数字比较大并且m比较大?

如何求解所有的子序列问题?

1.暴力解法复杂度O(2 ^ N)

2.背包解法(为什么能想到这个问题)复杂度O(N*SUM) N代表数组的长度,SUM代表数组累加和
子序列和背包问题的关系:
使用动态规划何求出数组arr所有的累加和
累加和数组不能太大;
dp[i][j]的含义:数组在arr[0…i]的之间的元素的累加和能否为j

状态转移方程:
dp[i][j] = dp[i-1][j] // 不选择第i个元素
| dp[i-1][j-arr[i]] //选择第i个元素

3.重新定义动态规划的状态:时间复杂度O(M*N) N代表数组的长度
dp[i][j] 代表的含义是:在数组arr[0…i]之间的元素是否存在累加和对m求余数的结果为j

4.二分解法,采用分治的思想

暴力解法:

 //第一种方式也就是暴力求解
    //共有2^n次方中可能性;每个位置都有两种可能性,选择或者不选择
    //时间复杂度过高
    private int getSubsequenceMaxModMForce(int[] arr, int m) {
   
        int res = 0;
        Set<Integer> set = new HashSet<>();
        processForce(arr, 0, 0, set);

        for (Integer num : set) {
   
            res = Math.max(res, num % m);
        }

        return res;
    }

    /**
     * 参数说明
     *
     * @param arr 原数组
     * @param cur 当前待处理的角标位置
     * @param sum 累加和
     * @param set 所有累加和的集合
     */
    private void processForce(int[] arr, int cur, int sum, Set<Integer> set) {
   
        if (cur == arr.length) {
   
            set.add(sum);
            return;
        }
        processForce(arr, cur + 1, sum, set);
        processForce(arr, cur + 1, sum + arr[cur], set);
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值