软件工程(2018)第三次作业

Posted sequix

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件工程(2018)第三次作业相关的知识,希望对你有一定的参考价值。

最大子段和

令f[i]为从莫一点开始到a[i]为止最大的子段和,则有以下转移方程:

\[f_i = \max(f_{i-1} + a[i], a[i])\]

因为只需遍历一次数组就可求出,所以复杂度为\(O(n)\)

package org.sequix.homework3;

/**
 * 提供求最大子段和的工具类。
 *
 * @author sequix
 * @version 0.0.1
 * @since 2018/03/26
 */
public class MaxSubArray {

    /**
     * 返回数组的最大子段和。
     * f[i] 到a[i]为止最大的子段和。
     * f[i] = max(f[i-1]+a[i], a[i])
     * 
     * @param arr 被求数组
     * @return 最大子段和
     */
    public static int msa(int[] arr) {
        if (arr.length == 0) {
            throw new IllegalArgumentException("expected a non-empty array");
        }
        
        int cur = arr[0];
        int ans = cur;
        
        for (int i = 1, len = arr.length; i < len; ++i) {
            cur += arr[i];
            if (arr[i] > cur) cur = arr[i];
            if (cur > ans) ans = cur;
        }
        return ans;
    }
}

测试

为了方便的测试,这里另写了一个工具类TestUtils。

在TestUtils.msa中,以另一种方式求最大子段和。其枚举所有的子段,选出最大的。此解法时间复杂度为\(O(n^2)\),但其正确性显而易见,所以用于对拍测试。

package org.sequix.homework3;

import java.util.Random;

/**
 * 提供测试用工具函数。
 * @author squix
 * @since 2018/03/19
 */
class TestUtils {
    private static Random random = new Random(); 
    
    /**
     * 生成[min, max]范围内的随机数。
     * @param min 最小值,最小可为Integer.MIN_VALUE
     * @param max 最大值,最大可为Integer.MAX_VALUE
     * @return 生成的随机数
     */
    static int randomInteger(int min, int max) {
        long num = (long) max - min + 1;
        long kth = (long) (random.nextDouble() * num);
        long ret = (long) min + kth;
        return (int) ret;
    }
    
    /**
     * 生成随机数数组。
     * @param size 数组大小
     * @param minElement 元素最小值
     * @param maxElement 元素最大值
     * @return 生成的数组
     */
    static int[] generateRandomArray(int size, int minElement, int maxElement) {
        int[] arr = new int[size];
        for (int i = 0; i < size; ++i)
            arr[i] = TestUtils.randomInteger(minElement, maxElement);
        return arr;
    }
    
    /**
     * 返回数组的最大子段和。用于和MaxSubArry.msa()对拍。
     * @param arr 被求数组
     * @return 最大子段和
     */
    static int msa(int[] arr) {
        int length = arr.length;
        int[] sum = new int[arr.length];
        
        sum[0] = arr[0];
        for (int i = 1; i < length; ++i) {
            sum[i] = sum[i-1] + arr[i];
        }
        
        int ans = arr[0];
        for (int left = 0; left < length; ++left) {
            for (int right = left; right < length; ++right) {
                int tmp = sum[right];
                if (left > 0) tmp -= sum[left-1];
                if (ans < tmp) ans = tmp;
            }
        }
        return ans;
    }
}

具体的测试类如下:

package org.sequix.homework3;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

/**
 * MaxSubArray 的测试类。
 *
 * @author sequix
 * @version 0.0.1
 * @since 2018/03/26
 */
@RunWith(JUnitPlatform.class)
public class MaxSubArrayTest {
    @Test(expected=IllegalArgumentException.class)
    public void testEmptyArray() {
        int[] original = new int[0];
        MaxSubArray.msa(original);
    }
    
    @Test
    public void testGeneral() {
        int[] original = new int[] {-2, 11, -4, 13, -5, -2};
        int expected = TestUtils.msa(original);
        assertEquals(expected, MaxSubArray.msa(original));
    }
    
    @Test
    public void testOnlyNegatives() {
        int[] original = TestUtils.generateRandomArray(10000, -10000, -1);
        int expected = TestUtils.msa(original);
        assertEquals(expected, MaxSubArray.msa(original));
    }
    
    @Test
    public void testOnlyPositives() {
        int[] original = TestUtils.generateRandomArray(10000, 1, 10000);
        int expected = TestUtils.msa(original);
        assertEquals(expected, MaxSubArray.msa(original));
    }
    
    @RepeatedTest(10)
    public void testRandom() {
        int[] original = TestUtils.generateRandomArray(10000, -10000, 10000);
        int expected = TestUtils.msa(original);
        assertEquals(expected, MaxSubArray.msa(original));
    }
}

测试效果

技术分享图片

外链

代码:Github

以上是关于软件工程(2018)第三次作业的主要内容,如果未能解决你的问题,请参考以下文章

软件工程(2018)第三次作业

软件工程(2018)第三次团队作业

软件工程(2018)第三次团队作业

软件工程(2018)第三次作业

软件工程(2018)第三次团队作业

软件工程(2018)第三次团队作业