最大子串和、积

1、最大子串和

endMax[i]表示以第i项为结尾的子串最大和
状态转移方程:

dp[i] = max(dp[i-1]+arr[i],arr[i],dp[i-1])

代码实现:

    /**
     * 子串最大和
     * 
     * @param arr
     * @return
     */
    static int getMaxSubStringSum(int[] arr) {
        int[] end = new int[arr.length];
        end[0] = arr[0];
        int sum = arr[0];
        int s = 0, e = 0;
        for (int i = 1; i < arr.length; i++) {
            int m = end[i - 1] + arr[i];
            end[i] = Math.max(m, arr[i]);
            if (end[i] == m) {
                e = i;
            } else {
                s = i;
                e = i;
            }
            sum = Math.max(end[i], sum);
        }
        System.out.println(s + "," + e);
        return sum;
    }

    /**
     * 减少空间复杂度,endMax数组直接用一个变量表示
     * 
     * @param arr
     * @return
     */
    static int getMaxSubStringSum2(int[] arr) {
        int endMax = arr[0];// 以第i项为结尾的子串最大和
        int sum = arr[0];
        int s = 0, e = 0;
        for (int i = 1; i < arr.length; i++) {
            int m = endMax + arr[i];
            endMax = Math.max(m, arr[i]);
            if (endMax == m) {
                e = i;
            } else {
                s = i;
                e = i;
            }
            sum = Math.max(endMax, sum);
        }
        System.out.println(s + "," + e);
        return sum;
    }

2、最大子串积

由于积可负负得正,正负得负,最大值可“瞬间”变为最小值,最小值可“瞬间”变为最大值,所以需要每次记录最大值和最小值
状态转移方程:

endMax[i] = max(max(endMax[i-1]*arr[i],endMin[i-1]*arr[i]),arr[i])
endMin[i] = min(min(endMax[i-1]*arr[i],endMin[i-1]*arr[i]),arr[i])

代码实现:

    /**
     * 子串最大积
     * 
     * @param arr
     * @return
     */
    static int getMaxSubStringProduct(int[] arr) {
        int[] endMax = new int[arr.length];
        int[] endMin = new int[arr.length];
        endMax[0] = arr[0];
        endMin[0] = arr[0];
        int result = arr[0];
        int s = 0, e = 0;// 记录子串起始下标
        for (int i = 1; i < arr.length; i++) {
            int m1 = Math.max(endMax[i - 1] * arr[i], endMin[i - 1] * arr[i]);
            endMax[i] = Math.max(m1, arr[i]);

            // 记录下标
            if (endMax[i] == m1) {
                e = i;
            }
            if (endMax[i] == arr[i]) {
                s = i;
                e = i;
            }

            int m2 = Math.min(endMax[i - 1] * arr[i], endMin[i - 1] * arr[i]);
            endMin[i] = Math.min(m2, arr[i]);
            result = Math.max(endMax[i], result);
        }
        System.out.println(s + "," + e);
        return result;
    }

    /**
     * 减少空间复杂度,end数组直接用一个变量表示
     * 
     * @param arr
     * @return
     */
    static int getMaxSubStringProduct2(int[] arr) {
        int endMax = arr[0];
        int endMin = arr[0];
        int result = arr[0];
        int s = 0, e = 0;// 记录子串起始下标
        for (int i = 1; i < arr.length; i++) {
            int m = Math.max(endMax * arr[i], endMin * arr[i]);
            endMax = Math.max(m, arr[i]);

            // 记录下标
            if (endMax == m) {
                e = i;
            }
            if (endMax == arr[i]) {
                s = i;
                e = i;
            }

            endMin = Math.min(Math.min(endMax * arr[i], endMin * arr[i]), arr[i]);
            result = Math.max(endMax, result);
        }
        System.out.println(s + "," + e);
        return result;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是我为您准备的100道Java算法题: 1. 翻转字符串 2. 在数组中查找重复数字 3. 单例模式 4. 冒泡排序 5. 快速排序 6. 选择排序 7. 插入排序 8. 希尔排序 9. 归并排序 10. 桶排序 11. 堆排序 12. 计数排序 13. 二叉树的遍历 14. 二叉树的深度 15. 二叉树的最大深度 16. 二叉树的最小深度 17. 二叉树的最大宽度 18. 二叉树的节点个数 19. 二叉树的叶子节点个数 20. 二叉树的高度 21. 二叉树的镜像 22. 二叉树的中序遍历 23. 二叉树的前序遍历 24. 二叉树的后序遍历 25. 二叉树的层次遍历 26. 二叉树的层次遍历 II 27. 二叉树的锯齿形层次遍历 28. 二叉树的最近公共祖先 29. 二叉树的路径和 30. 二叉树的路径和 II 31. 二叉树的所有路径 32. 二叉树的所有路径 II 33. 二叉树的最长连续序列 34. 二叉树的最深叶子节点的最近公共祖先 35. 二叉树的最大路径和 36. 二叉树的最小深度 II 37. 二叉树的右视图 38. 二分查找 39. 二分查找的变体 40. 二叉搜索树的插入 41. 二叉搜索树的删除 42. 两数之和 43. 三数之和 44. 四数之和 45. 无重复字符的最长子串 46. 最长回文子串 47. 最长公共前缀 48. 字符串中的第一个唯一字符 49. 罗马数字转整数 50. 整数转罗马数字 51. 最大子序和 52. 最长上升子序列 53. 最长公共子序列 54. 最长回文子序列 55. 编辑距离 56. 最长有效括号 57. 最长公共子串 58. 最长连续递增序列 59. 最长连续递减序列 60. 最长连续重复子串 61. 最长重复子数组 62. 最短无序连续子数组 63. 最长的斐波那契子序列的长度 64. 最长等差数列 65. 最长连续子序列 66. 最长湍流子数组 67. 最长子数组的和 68. 最小覆盖子串 69. 最小路径和 70. 最小栈 71. 最大栈 72. 最小栈和最大栈的实现 73. 最小栈和最大栈的查找 74. 最小栈和最大栈的删除 75. 最小栈和最大栈的修改 76. 最小栈和最大栈的插入 77. 最小栈和最大栈的求和 78. 最小栈和最大栈的求差 79. 最小栈和最大栈的求 80. 最小栈和最大栈的求商 81. 最小栈和最大栈的求余 82. 最小栈和最大栈的排序 83. 最小栈和最大栈的反转 84. 最小栈和最大栈的合并 85. 最小栈和最大栈的交集 86. 最小栈和最大栈的并集 87. 最小栈和最大栈的差集 88. 最小栈和最大栈的对称差 89. 最小栈和最大栈的求最大值 90. 最小栈和最大栈的求最小值 91. 最小栈和最大栈的求中位数 92. 最小栈和最大栈的求平均值 93. 最小栈和最大栈的求方差 94. 最小栈和最大栈的求标准差 95. 最小栈和最大栈的求众数 96. 最小栈和最大栈的求众数 II 97. 最小栈和最大栈的求众数 III 98. 最小栈和最大栈的求众数 IV 99. 最小栈和最大栈的求众数 V 100. 最小栈和最大栈的求众数 VI 希望这些算法题能够对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值