14天阅读挑战赛
努力是为了不平庸~
算法学习有些时候是枯燥的,这一次,让我们先人一步,趣学算法!
算法知识点
算法复杂度,即算法在编写写成可执行程序后,运行时所需要的资源,资源包括时间资源和内存资源。
时间复杂度 即 时间资源消耗
空间复杂度 即 内存资源(输入输出数据,算法本身,算法运行所需的辅助变量)消耗
算法题目来源
有一个古老的传说,一位国王的女儿不幸落水,水中有很多鳄鱼,国王情急之下下令:“谁能把公主救上来,就把女儿嫁给他。”很多人纷纷退让,一个勇敢的小伙子挺身而出,冒着生命危险把公主救了上来,国王一看是个穷小子,想要反悔,说:“除了女儿,你要什么都可以。”小伙子说:“好吧,我只要一棋盘的麦子。您在第1个格子里放1粒麦子,在第2个格子里放2粒,在第3个格子里放4粒,在第4个格子里放8粒,以此类推,每一个格子里麦子的粒数都是前一格子里麦子粒数的两倍。把这64个格子放满了就行,我就要这么多。”国王听后哈哈大笑,觉得小伙子的要求很容易满足,满口答应。结果发现,把全国的麦子都拿来,也填不完这64个格子……国王无奈,只好把女儿嫁给了这个小伙子。
算法题目描述
第1个格子里放1粒麦子,在第2个格子里放2粒,在第3个格子里放4粒,在第4个格子里放8粒,以此类推,每一个格子里麦子的粒数都是前一格子里麦子粒数的两倍,把这64个格子放满,总共放多少粒麦子
题目已知
1,格子数 n : 3 <= n <=64
2, 总共的麦子数:S = 1+2+ ······+2^(n-1)
按已知直接计算
代码:
public static double simpleTotalWheat(int n){ double total = 0L; // 运行1次 while (n > 0){ // 运行 n+1 次 total += Math.pow(2,n-1); //运行n次 n--; //运行n次 } return total; } public static void main(String[] args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); double total = simpleTotalWheat(64); stopWatch.stop(); log.info("总数:{},消耗时间(纳秒):{}",total,stopWatch.getTime(TimeUnit.NANOSECONDS)); }
结果:
总数:1.8446744073709552E19,消耗时间(纳秒):26292
算法分析:
1,时间复杂度:1+n+1+n+n, T(n)表达式:T(n) = 2+3n, 时间复杂度呈线性增长
2,空间复杂度:从方法返回值可以看出,主要空间占用在 total 辅助变量的占用,而且这个变量需要变换n次,且在不断增长
优化算法
算法推导
S = 1+2+ ······+2^(n-1); 2*S = 2+4+·······2^n; 2S-S = 2^n - 1 S = 2^n - 1
代码实现
/** * 算法优化 S = 1+2+ ······+2^(n-1); 2*S = 2+4+·······2^n; 2S-S = 2^n - 1 S = 2^n - 1 * @param n * @return */ public static double easyTotalWheat(int n){ return Math.pow(2,n)-1; //运行一次 } public static void main(String[] args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); double total = easyTotalWheat(64); stopWatch.stop(); log.info("总数:{},消耗时间(纳秒):{}",total,stopWatch.getTime(TimeUnit.NANOSECONDS)); }
结果:
总数:1.8446744073709552E19,消耗时间(纳秒):13167
算法分析:
1,时间复杂度 : 1
2,空间复杂度: 1
总结
1,只要能解决问题就可以称之为算法
2,然而算法的优劣,对资源的占用天差地别
3,遇到问题多思考,算法的优化很有必要