算法初步 基本概念 最大子数组和
算法是研究时空复杂度的,时空复杂度使用大O表示。
时间:基本操作次数(汇编指令条数,比如算法执行完需要n行指令,则时间复杂度为O(n),时间复杂度是忽略前面的系数的,算法执行需要2n行指令,时间复杂度也是O(n),所以不用考虑一行指令对应多条汇编,系数是忽略的。O(n^2 + n)可以认为是o(n^2),因为n的平方远大于n) 空间:占用内存字节数
优秀的算法:O(1) < O(logn) < O(n^1/2) < O(n) < O(nlogn) 需要优化的算法:O(n^2) < O(n^3) < O(2^n) < O(n!)
案例 最大子数组求和 leetcode 53题 给定数组a[1…n],求最大子数组和,即找出1<=i<=j<=n,使a[i]+a[i+1]+…+a[j]最大。
方法一:暴力枚举,时间复杂度为o(n^3),无法通过leetcode,显示超时。 时间复杂度为o(n^3),空间复杂度o(1)
class Solution {
public int maxSubArray(int[] nums) {
int sum = 0;
int msum = Integer.MIN_VALUE;
for(int i=0;i<nums.length;i++){
for(int j=i;j<nums.length;j++){
for(int k=i;k<=j;k++){
sum+=nums[k];
}
if(msum<sum){
msum = sum;
}
sum = 0;
}
}
return msum;
}
}
方法二:优化枚举,时间复杂度为o(n^2),空间复杂度为o(n)(很多部分都重复加了,要去除冗余,直接通过了leetcode,很神奇,执行时间为66ms,超过了百分之4的人。
class Solution {
public int maxSubArray(int[] nums) {
int sum = 0;
int msum = Integer.MIN_VALUE;
int[] s = new int[nums.length + 1];
s[0] = 0;
for(int i=0;i<nums.length;i++){
s[i + 1] = s[i] + nums[i];
}
for(int i=0;i<nums.length;i++){
for(int j=i;j<nums.length;j++){
sum = s[j+1] - s[i];
if(msum<sum) msum = sum;
}
}
return msum;
}
}
方法三:假设s[i] 为nums[0] 到nums[i]的和,那么要想求出最大子数组和,就需要得到max(s[j] - s[i]),将s[j]固定,则需要求min(s[i]),所以此问题由最大子数组和转换成了求最小和(最小s[i])的问题,这次提交执行时间为10ms,超过了47.22%的人 (经验:求和变求差 求积变求和 求指数变对数 求最大变求最小),时间复杂度为O(n),空间复杂度为O(n)。
class Solution {
public int maxSubArray(int[] nums) {
int msum = Integer.MIN_VALUE;
int si = 0;
int sj = 0;
int minsi = 0;
for(int j = 0; j<nums.length;j++){
sj += nums[j];
if(si < minsi){ //min[0,6] = min(min[0,5] [6]) 求最小和可以通过增量来实现,si的(0,6)的最小和其实就是(0,5)的si最小和和si[6]最比较,这种增量方式的转换技巧很实用
minsi = si;
}
if(sj - minsi > msum){
msum = sj - minsi;
}
si += nums[j];
}
return msum;
}
}
方法四:将以上代码稍微调整一下就是贪心算法了 时间8ms,超过89.81%。贪心算法的思路比较难以理解,后面介绍贪心算法的时候再回过头来看看。
class Solution {
public int maxSubArray(int[] nums) {
int msum = Integer.MIN_VALUE;
int sum = 0;
for(int j = 0; j<nums.length;j++){
sum += nums[j];
if(sum>msum) msum = sum;
if(sum < 0) sum = 0;
}
return msum;
}
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Laravel框架视图和模型操作方法分析
- 接口测试框架实战(六) | 配置的数据驱动
- PHP连续签到功能实现方法详解
- PHP实现发送微博消息功能完整示例
- php实现快速对二维数组某一列进行组装的方法小结
- PHP实现提取多维数组指定一列的方法总结
- PHP实现二维数组(或多维数组)转换成一维数组的常见方法总结
- Laravel框架Eloquent ORM简介、模型建立及查询数据操作详解
- Laravel框架下载,安装及路由操作图文详解
- PHP实用小技巧之调用录像的方法
- Laravel重定向,a链接跳转,控制器跳转示例
- Laravel 错误提示本地化的实现
- Laravel框架DB facade数据库操作详解
- laravel 解决强制跳转 https的问题
- 在laravel中实现将查询的对象转换为多维数组的函数