Middle-题目112:152. Maximum Product Subarray

题目原文:
Find the contiguous subarray within an array (containing at least one number) which has the largest product.

For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.
题目大意:
寻找最大乘积的连续子数组。
题目分析:
使用两个dp数组dpmax和dpmin,其中dpmax[i]和dpmin[i]分别表示以i为结尾的子数组的最大、最小乘积。那么初始化dpmax[0]和dpmin[0]均为nums[0],转移方程如下:
dpmax[i]=max(nums[i],dpmax[i1]nums[i],dpmin[i1]nums[i])
dpmin[i]=min(nums[i],dpmax[i1]nums[i],dpmin[i1]nums[i])
这是因为nums[i]可能是正数也可能是负数,如果是负数且前一项的最小积是负数,则会变成最大乘积,而如果最大乘积和最小乘积都是负数或0,且nums[i]是正数,则它本身是最大乘积。所以最大值和最小值可能有三种情况。
源码:(language:java)

public class Solution {
    public int maxProduct(int[] nums) {
        int length = nums.length;
        if(length==0)
            return 0;
        int[] dpmax = new int[length];
        int[] dpmin = new int[length];
        dpmax[0] = nums[0];
        dpmin[0] = nums[0];
        int max = dpmax[0];
        for(int i = 1;i<length;i++) {
            dpmax[i] = max(nums[i],dpmax[i-1]*nums[i],dpmin[i-1]*nums[i]);
            dpmin[i] = min(nums[i],dpmax[i-1]*nums[i],dpmin[i-1]*nums[i]);
            if(dpmax[i]>max)
                max=dpmax[i];
        }
        return max;
    }
    private int max(int a,int b,int c) {
        return a>b?(a>c?a:c):(b>c?b:c);
    }
    private int min(int a,int b,int c) {
        return a<b?(a<c?a:c):(b<c?b:c);
    }
}

成绩:
5ms,beats 10.47%,众数5ms,36.73%
cmershen 的碎碎念:
(1) 本题如果用一个dp数组,即dp[i][j]维护从i~j的最大乘积,也能实现但会超时。
(2) 对nums很长的情况下,可能会涉及到BigInteger高精度计算,题中没有超过int范围,故test case不够严密。
(3) 这是第一次遇到同时维护多个dp数组的题,也是拓宽了思路。

资源下载链接为: https://pan.quark.cn/s/d9ef5828b597 在本文中,我们将探讨如何通过 Vue.js 实现一个带有动画效果的“回到顶部”功能。Vue.js 是一款用于构建用户界面的流行 JavaScript 框架,其组件化和响应式设计让实现这种交互功能变得十分便捷。 首先,我们来分析 HTML 代码。在这个示例中,存在一个 ID 为 back-to-top 的 div 元素,其中包含两个 span 标签,分别显示“回到”和“顶部”文字。该 div 元素绑定了 Vue.js 的 @click 事件处理器 backToTop,用于处理点击事件,同时还绑定了 v-show 指令来控制按钮的显示与隐藏。v-cloak 指令的作用是在 Vue 实例渲染完成之前隐藏该元素,避免出现闪烁现象。 CSS 部分(backTop.css)主要负责样式设计。它首先清除了一些默认的边距和填充,对 html 和 body 进行了全屏布局,并设置了相对定位。.back-to-top 类则定义了“回到顶部”按钮的样式,包括其位置、圆角、阴影、填充以及悬停时背景颜色的变化。此外,与 v-cloak 相关的 CSS 确保在 Vue 实例加载过程中隐藏该元素。每个 .page 类代表一个页面,每个页面的高度设置为 400px,用于模拟多页面的滚动效果。 接下来是 JavaScript 部分(backTop.js)。在这里,我们创建了一个 Vue 实例。实例的 el 属性指定 Vue 将挂载到的 DOM 元素(#back-to-top)。data 对象中包含三个属性:backTopShow 用于控制按钮的显示状态;backTopAllow 用于防止用户快速连续点击;backSeconds 定义了回到顶部所需的时间;showPx 则规定了滚动多少像素后显示“回到顶部”按钮。 在 V
<think>嗯,用户遇到了问题,说分治算法的结果和蛮力算法的结果不一致,导致效率提升显示为-1.00倍,这可能意味着分治算法的实现有错误。首先,我需要仔细检查用户提供的代码,特别是分治算法的部分。 分治算法通常将数组分成左右两部分,分别计算左右的最大子数组和,然后处理跨越中点的子数组。用户的分治辅助函数是否正确处理了这三种情况?比如,在计算跨中点的最大和时,是否正确地从中间向左右扩展,并累加最大值? 另外,用户生成的测试数组范围是-100到100,可能包含负数,这时候如果所有数都是负数,最大子数组和应该是最大的那个负数。但用户的分治算法是否正确处理了这种情况?比如,在递归基准情况中,当left等于right时,直接返回arr[left],而没有考虑是否为负数的情况,这其实是正确的,因为单个元素本身就是最大子数组。 接下来,检查跨中点的计算。在用户的代码中,left_sum和right_sum初始化为INT_MIN,这可能有问题。例如,如果数组中的元素都是负数,那么left_sum和right_sum可能不会被正确更新,导致cross_max计算错误。正确的做法应该是初始化sum为0,然后逐步累加,并比较当前sum与最大和。或者,如果允许空数组,则需要另外处理,但题目中应该不允许空子数组。 再来看用户的测试方法,分治算法测试的是100,000个元素,而蛮力算法只测试前100个元素。这里可能存在不一致,因为分治算法处理的是整个大数组,而蛮力算法只处理前100个元素。用户可能在比较两个不同范围的结果,导致结果不一致。例如,分治算法计算的是整个大数组的最大子数组和,而蛮力算法计算的只是前100个元素的子数组和,这显然是不同的输入,自然结果不同。这就是问题所在! 用户可能误解了测试方法,正确的做法应该是对于同一个数组,比如前100个元素,同时用分治和蛮力算法计算,确保结果一致。而用户当前的代码中,分治算法处理的是整个100,000元素的数组,而蛮力算法只处理前100元素,这导致结果无法比较。因此,输出结果的不同是因为它们处理的是不同的数据部分,自然结果不同,所以效率对比也没有意义。 另外,效率提升的计算方式是否正确?用户计算的是(t2 - t1)/t2,但当t2比t1小的时候,这里得出的负数可能被错误地显示为效率提升。比如,用户的结果中分治耗时0.001925秒,而蛮力处理小数据用了0.000003秒,这时候分治反而更慢,导致效率提升为负数,但用户的计算方式可能有问题,应该用t2 / t1来表示分治比蛮力快了多少倍,或者相反。 总结问题原因:测试时分治和蛮力处理的数据规模不同,导致结果无法比较。正确的测试方法应使用相同的数据集,比如用较小的数据规模(如100个元素)同时用两种算法计算,验证结果是否一致,然后再测试分治在大数据上的性能。用户当前的代码中,分治处理的是整个大数组,而蛮力只处理前100个元素,所以结果不一致是正常的,但用户误以为这是错误。 解决方案是修改测试逻辑,让两种算法处理相同的数据,例如将分治和蛮力都处理前brute_size(100)个元素,并比较结果是否一致。同时,可以添加正确性验证步骤,如果结果不同则报错。此外,效率提升的计算方式也需要调整,可能应该比较在相同数据规模下的执行时间,或者分别处理不同规模的数据,但说明分治在大数据时的优势。</think>您遇到的异常输出源于测试逻辑中的三个关键问题,以下是详细分析和解决方案: **一、问题诊断** 1. **测试数据不一致**(核心问题) ```c int result_divide = max_subarray_divide(test_arr, divide_size); // 测试整个大数组 int result_brute = improved_brute_force(test_arr, brute_size); // 仅测试前100元素 ``` - 分治算法处理10万元素的完整数组 - 蛮力算法仅处理前100个元素 - **比较的是不同数据范围的结果,必然不一致** 2. **效率计算逻辑错误** ```c double efficiency = (t2 > t1) ? (t2 - t1)/t2 : -(t1 - t2)/t1; ``` - 当t1(分治耗时)> t2(蛮力耗时)时,计算值为负数 - 正确公式应为:`效率倍数 = 老时间 / 新时间` 3. **分治算法边界问题** ```c int mid = (left + right) / 2; // 整数溢出风险 ``` **二、修正后的完整代码** ```c #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <time.h> #include <windows.h> // 改进的蛮力算法(保持不变) int improved_brute_force(int arr[], int n) { /* 原代码 */ } // 修正后的分治算法 int max_subarray_helper(int arr[], int left, int right) { if (left == right) return arr[left]; int mid = left + (right - left) / 2; // 防溢出写法 int left_max = max_subarray_helper(arr, left, mid); int right_max = max_subarray_helper(arr, mid+1, right); // 修正跨中点计算 int left_sum = 0, max_left = INT_MIN; for (int i = mid; i >= left; i--) { left_sum += arr[i]; if (left_sum > max_left) max_left = left_sum; } int right_sum = 0, max_right = INT_MIN; for (int i = mid+1; i <= right; i++) { right_sum += arr[i]; if (right_sum > max_right) max_right = right_sum; } int cross_max = max_left + max_right; // 三者取最大 int max_val = (left_max > right_max) ? left_max : right_max; return (max_val > cross_max) ? max_val : cross_max; } int max_subarray_divide(int arr[], int n) { /* 原代码 */ } // 生成测试数组(保持不变) void generate_test_array(int arr[], int n) { /* 原代码 */ } int main() { const int test_size = 100; // 统一测试规模 int* test_arr = (int*)malloc(test_size * sizeof(int)); generate_test_array(test_arr, test_size); LARGE_INTEGER freq, t1, t2; QueryPerformanceFrequency(&freq); // 正确性验证 QueryPerformanceCounter(&t1); int result_divide = max_subarray_divide(test_arr, test_size); QueryPerformanceCounter(&t2); double time_divide = (double)(t2.QuadPart - t1.QuadPart) / freq.QuadPart; QueryPerformanceCounter(&t1); int result_brute = improved_brute_force(test_arr, test_size); QueryPerformanceCounter(&t2); double time_brute = (double)(t2.QuadPart - t1.QuadPart) / freq.QuadPart; // 结果输出 printf("分治结果: %d, 耗时: %.6f秒\n", result_divide, time_divide); printf("蛮力结果: %d, 耗时: %.6f秒\n", result_brute, time_brute); // 正确性检查 if (result_divide != result_brute) { printf("\033[31m错误: 结果不一致!请检查算法实现\033[0m\n"); } else { printf("效率对比: 分治比蛮力快 %.2f 倍\n", time_brute / time_divide); } free(test_arr); return 0; } ``` **三、关键修改说明** 1. **统一测试规模** ```c const int test_size = 100; // 两种算法测试相同数据 ``` - 确保比较的是同一数据集的结果 - 先验证正确性,再单独测试分治算法的大数据性能 2. **修正分治算法** - 修改中点计算方式防溢出:`mid = left + (right - left)/2` - 优化跨中点计算逻辑,显式使用`max_left`和`max_right` 3. **合理的效率对比** ```c time_brute / time_divide // 直接计算倍数关系 ``` - 正值表示分治更快 - 例如:蛮力耗时0.1秒,分治0.01秒 → 效率提升10倍 4. **增加结果验证** ```c if (result_divide != result_brute) { printf("\033[31m错误: 结果不一致!\033[0m\n"); } ``` - 当结果不一致时显示红色错误提示 - 确保算法正确性优先于性能测试 **四、验证测试** 1. **典型正确输出** ``` 分治结果: 542, 耗时: 0.000115秒 蛮力结果: 542, 耗时: 0.000347秒 效率对比: 分治比蛮力快 3.02 倍 ``` 2. **错误检测示例** ``` 分治结果: 315, 耗时: 0.000121秒 蛮力结果: 542, 耗时: 0.000332秒 错误: 结果不一致!请检查算法实现 ``` **五、进一步调试建议** 1. **小数据测试** ```c // 手动设置测试用例 int debug_arr[] = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; int debug_size = sizeof(debug_arr)/sizeof(int); ``` 正确结果应为6(子数组[4,-1,2,1]) 2. **添加调试输出** ```c // 在分治递归中添加 printf("Processing [%d-%d], current max: %d\n", left, right, current_max); ``` 3. **边界值测试** - 全负数数组:{-5, -3, -2} - 全正数数组:{2, 5, 3} - 单元素数组:{7} 请先使用修正后的代码验证,如果仍存在问题,可以提供具体的测试用例以便进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值