文章目录

  • 前言
  • 一、递归
  • 二、求最大子序列和
    • 1,最朴素的解法
    • 2,较朴素的解法(更进一步)
    • 3,分治和递归
    • 4,精妙的解法
  • 总结

前言

本文简单介绍递归的使用(依次打印出一个 int 整数的每一位)和求最大子序列的方法(以 int 数组为例)。

一、递归

递归的基本法则:
      1,基准情形:能够直接解出结果的情形。
      2,不断推进:保证每一次递归调用能向基准情形推进。
      3,设计法则:所有的递归调用都能运行。(一般不考虑这点)
      4,合成效益法则:在求解一个问题时,切忌在不同的递归调用中做重复性的工作。比如:求斐波那契数列中的: f(n)=f(n-1)+f(n-2)。 f(n-2) 被单独计算一次,但是当计算 f(n-1) 时,f(n-2) 又被计算一次,以此类推,程序做了大量重复性的工作。

递归示例,依次打印出一个整数的每一位:

public final class HelloWorld {public static void print(int n){if(n>=10)print(n/10);System.out.println(n%10);}public static void main(String[] args){int n=12345678;if(n>=0&&n<=Integer.MAX_VALUE)print(n);}
}

二、求最大子序列和

1,最朴素的解法

其思想为:将一个序列的所有可能的子序列和都计算一遍,取最大值。最外层循环 i 用来标记待计算序列的起始下标,j 用来标记待计算序列的结束下标,k 用来遍历待计算序列,得到其和,并且保留最大的序列和值。

该解法的时间复杂度为O(n3)。

public static int findMaxSeries_1(int[] n){int re=Integer.MIN_VALUE,tmp;for(int i=0;i<n.length;i++)for(int j=i;j<n.length;j++) {tmp=0;for(int k=i;k<j+1;k++)tmp+=n[k];if(re<tmp)re=tmp;}return re;}

2,较朴素的解法(更进一步)

上面代码中在 j 循环中,可以在 j 每次变化时计算新的子序列和并判断大小,从而可以省掉不必要的最内层循环:

该解法的时间复杂度为O(n2)。

public static int findMaxSeries_2(int[] n){int re=Integer.MIN_VALUE,tmp;for(int i=0;i<n.length;i++){tmp=0;for(int j=i;j<n.length;j++) {tmp+=n[j];if(re<tmp)re=tmp;}}return re;}

3,分治和递归

试一下时间复杂度为O(nlogn)的解法。采用分治的思想,那需要将原序列分为两个子序列来计算(递归进行分配,直到设定的某个约束条件),原序列的最大子序列和有三种情况:1,当最大子序列在左边序列时:它的值为左边序列中的最大子序列和值;2,当最大子序列在右边序列时:它的值为右边序列中的最大子序列和值;3,当最大子序列横跨左右序列时:此时需要,从左右两边的分界线处开始计算,分别求左边和右边序列中的最大值(时间复杂度为 O(n)),然后左右相加便得到结果。

具体地见下面代码:

    public static int findMaxSeries_3(int[] n){return findMaxSeries_3_1(n,0,n.length-1);}public static int findMaxSeries_3_1(int[] n, int left, int right){if(left==right)//当序列只有一个值的时候,直接返回。return n[left];int mid=(left+right)/2;int maxLeftSum= findMaxSeries_3_1(n,left,mid);int maxRightSum= findMaxSeries_3_1(n,mid+1,right);int maxLeftBorderSum=Integer.MIN_VALUE,leftBorderSum=0;for(int i=mid;i>=left;i--){leftBorderSum+=n[i];if(leftBorderSum>maxLeftBorderSum)maxLeftBorderSum=leftBorderSum;//求左边序列的最大值(从元素 n[center]开始)}int maxRightBorderSum=Integer.MIN_VALUE,rightBorderSum=0;for(int i=mid+1;i<=right;i++){rightBorderSum+=n[i];if(rightBorderSum>maxRightBorderSum)maxRightBorderSum=rightBorderSum;//求左边序列的最大值(从元素 n[center+1])开始)}return maxLeftSum>maxRightSum? maxLeftSum: Math.max(maxRightSum, (maxLeftBorderSum + maxRightBorderSum));}

4,精妙的解法

和上一个解法中求左右序列最大值的方法类似,不过需要带点儿变化。

1,在一次遍历中,刚开始保存一个元素组成的序列和,即它本身。
      2,当子序列长度加一时,此时子序列中有两个元素,判断此时的序列和与之前值 max 的大小关系,若比之前值大,就保存此时的序列和。如果当前序列和小于 0 ,那之前的序列就丢掉了,重置为 0,从下一个数重新开始 。
      3,最后由 max 返回最大值。

该解法的时间复杂度为O(n)。

    public static int maxSubArray(int[] nums) {int len=nums.length;int sum=0,max=Integer.MIN_VALUE;for(int i=0;i<len;i++){sum+=nums[i];if(sum>max)max=sum;if(sum<0)sum=0;}return max;}

总结

完,

LeetCode算法题3:求最大子序列和相关推荐

  1. leetcode算法题--最长公共子序列★

    原题链接:https://leetcode-cn.com/problems/longest-common-subsequence/ 动态规划 dp[i][j]表示text1[:i]和text2[:j] ...

  2. leetcode算法题-- 最长递增子序列的个数★

    原题链接:https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence/ 相关题目:最长上升子序列 lengths ...

  3. leetcode算法题--删除回文子序列

    原题链接:https://leetcode-cn.com/problems/remove-palindromic-subsequences/ class Solution {public:int re ...

  4. leetcode算法题--最长上升子序列

    原题链接:https://leetcode-cn.com/problems/longest-increasing-subsequence/ 思路是从后向前用动态规划,转移方程为 dp[i]=max(d ...

  5. Leetcode算法题:两个有序数组求中位数

    Leetcode算法题:两个有序数组求中位数 要求时间复杂度为O(log(m+n)) 思路: 暴力解决:合并数组并排序,简单且一定能实现,时间复杂度O(m+n) 由于两个数组已经排好序,可一边排序一边 ...

  6. LeetCode算法题整理(200题左右)

    目录 前言 一.树(17) 1.1.后序遍历 1.2.层次遍历 1.3.中序 1.4.前序 二.回溯(20) 2.1.普通回溯 2.2.线性回溯:组合.排列.子集.分割 2.3.矩阵回溯 三.二分查找 ...

  7. LeetCode算法题-Minimum Depth of Binary Tree(Java实现)

    这是悦乐书的第168次更新,第170篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第27题(顺位题号是111).给定二叉树,找到它的最小深度.最小深度是沿从根节点到最近的 ...

  8. LeetCode算法题-K-diff Pairs in an Array(Java实现)

    这是悦乐书的第254次更新,第267篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第121题(顺位题号是532).给定一个整数数组和一个整数k,您需要找到数组中唯一的k- ...

  9. LeetCode算法题-Nth Digit(Java实现)

    这是悦乐书的第215次更新,第228篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第83题(顺位题号是400).找到无限整数序列的第n个数字1,2,3,4,5,6,7,8 ...

最新文章

  1. ASP.NET 2.0 读取配置文件[INI](示例代码下载)
  2. 能打开java文件_用java打开一个本地文件
  3. 两个ListBox的相互操作
  4. PHP ERROR_php中的异常和错误浅析
  5. 结队开发之NABCD
  6. spring事务三大接口
  7. [css] 如何使用CSS实现段落首字母或首字放大效果?
  8. 小白 LeetCode 5605 检查两个字符串数据是否相等
  9. python单步调试的方法_python断点调试方法
  10. 敲了几年代码,是时候考虑以后的发展了
  11. 华为支付强势杀入,微信、支付宝迎来新对手!
  12. fpga初始化错误_FPGA的ROM初始化问题讨论
  13. 山东济南站见面会完美收官
  14. 初识C语言,入门小程序
  15. php excel引入tp,TP 引入phpExcel
  16. echarts3d城市配置项
  17. PDF文件拆分合并器PDF Merge PDF Splitter + Mac
  18. HP deskjet 2132 如何顺利在mac上使用
  19. 1635 超大型 LED 显示屏
  20. 关于Java中Match类的appendReplacement()方法的一个坑{ character to be escaped }

热门文章

  1. iOS 多线程的简单理解(3)执行方式 + 执行对列 的组合
  2. webApp开发-功能模块开发流程
  3. HDOJ 4704 Sum 规律 欧拉定理
  4. Python3安装配置【转】
  5. 推荐一本书给大家《不懂带人 你就自己做到死》
  6. MyEclipse 导出 javadoc 乱码解决
  7. javascript:document对象的常用属性和方法
  8. Win64 驱动内核编程-17. MINIFILTER(文件保护)
  9. 【Groovy】集合遍历 ( “ *. “ 展开操作符 | 代码示例 )
  10. 【组合数学】排列组合 ( 多重集排列 | 多重集全排列 | 多重集非全排列 所有元素重复度大于排列数 | 多重集非全排列 某些元素重复度小于排列数 )