Java科普之算法剖析

简介: 本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!       从小白晋升,一路走来;从helloworld,到JFrame,再到Android;从城外小子,到内城的阶...


本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!


       从小白晋升,一路走来;从helloworld,到JFrame,再到Android;从城外小子,到内城的阶梯,站在高耸入云的阶梯上向前望;从迷茫的时代,到苦逼的时代,再到自信的时代;这些路有些艰难,有些坎坷,但--还算顺利;有过困惑,有过烦恼,有过委屈,但一路向前,风雨无阻;前言是遥远的,前方是未知的,前方是广阔的,前方是美好的;我要呼吁广大IT同胞们,让我们向着更遥远、更广阔、更美好的充满未知的未来出发吧!去贪婪的吮吸每一滴“蜜露”,用知识的精髓武装自己,斗志昂扬一如既往的用兴趣开路,去探寻属于自己的一片天地!


       今天冒昧给大家讲讲算法的故事。


       在从简单的逻辑写起,从完成一个控件、多个控件,走了一条线程、一条进程;到完成一个模块、若干模块,实现界面之间的交互、控件自定义;再到缓存、数据库、网络交互,内存管理、系统调优、架构扩展;最后又回归逻辑、研究算法,研究层与层之间的调用、依赖,抽象、继承、接口、反射等一些基础的概念;简而言之,把最简单的东西做到极致,那牛逼了!


       百度解释:算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是指执行算法所需要的计算工作量;而空间复杂度是指执行这个算法所需要的内存空间。(算法的复杂性体现在运行该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度。)
       接下来依次讲几个算法,冒泡、选择……

       冒泡算法原理:两个两个的比较,其中较大的与较小的换位,每次都能排出剩下数中的最大数,放剩下数的最后;最终排出整齐的数列。 

        时间复杂度:倒序最大,Cmax=n*(n-1)/2,为T(n^2);正序最小,Cmin=n,为T(n);按实际情况来算。

        空间复杂度为:最坏情况,每两个就要换一回,则为n/2+(n-1)/2+……+2/2=n(n+1)/4,Omax=O(n^2);最好情况,已排好,则为O(0)。

        代码如下:

public void testBubbleSort() {

		int[] sortArray = { 4, 7, 9, 3, 6, 8,11 };
		for (int i = 0; i < sortArray.length-1 ; i++) {
			boolean isSort = false;
			for (int j = 0; j < sortArray.length -1-i; j++) {
				if (sortArray[j] > sortArray[j + 1]) {
					int temp = sortArray[j];
					sortArray[j] = sortArray[j + 1];
					sortArray[j + 1] = temp;
					isSort = true;
				}
			}
			if (!isSort)
				break;
		}
		System.out.println(Arrays.toString(sortArray));
	}

        选择排序原理:第一次,首个与后面的进行比较,把最小的放首位;第二次,次个与后面的进行比较,把次小的放次位;依次进行。

        与冒泡的区别在于:选择排序找出最小的下标,然后与此次开始位置数字置换,冒泡需要两个两个的换位置;从这个意义上来说,选择排序占用内存更少,拥有更小的空间复杂度。

        时间复杂度:最坏情况,n(n+1)/2,为Tmax=T(n^2);最好情况,已排好,则为T(n)。

        空间复杂度;最坏情况为O(n),最好为O(0),分别为正好相反或已排好。

        代码如下:

public void testChooseSort() {

		int min;
		for (int i = 0; i < sortArray.length - 1; i++) {
			min = i;
			for (int j = i + 1; j < sortArray.length - 1 - i; j++) {
				if (sortArray[min] > sortArray[j]) {
					min = j;
				}
			}
			if(min!=i){
				int temp=sortArray[min];
				sortArray[min]=sortArray[i];
				sortArray[i]=temp;
			}
		}
		System.out.println(Arrays.toString(sortArray));
	}

快速排序:从第2个开始,如果第2个比第1个大,则两者交换;第3个,放在前2个已经排序的队列中,合适的位置;第4个放在前3个已经排序的队列中,合适的位置;继续,最终直接排出有顺序的队列。


构建队列,计算二叉树叶子值的和

	static class TreeNode {
		int val;
		TreeNode left;
		TreeNode right;

		public TreeNode(int val) {
			this.val = val;
		}
	}

	/**
	 * 1 2 3 4 5 6 7
	 * 
	 * @param root
	 * @return
	 */
	public static void buildTree(TreeNode root) {
		if (root.val >= 4) {
			return;
		}
		TreeNode left = new TreeNode(root.val + 1);
		TreeNode right = new TreeNode(root.val + 2);
		root.left = left;
		root.right = right;
		buildTree(root.left);
		buildTree(root.right);
	}

	public static void main(String[] args) {
		TreeNode root = new TreeNode(1);
		buildTree(root);
		int sum = 0;
		System.out.println(sumTree(root, sum));
	}

	public static int sumTree(TreeNode root, int sum) {
		if (root == null)
			return sum;
		sum += root.val;
		sum = sumTree(root.left, sum);
		sum = sumTree(root.right, sum);
		return sum;
	}

贪心算法:

1、给分数不同的小朋友分糖果

2、旁边分数高的要比分数低的分的多

3、求最少糖果数

	public static int candy(int[] ratings) {
		if (ratings == null || ratings.length == 0)
			return 0;
		int[] candies = new int[ratings.length];
		for (int i = 0, size = ratings.length; i < size; i++) {
			if (i == 0) {
				candies[i] = 1;
				continue;
			}
			if (ratings[i] > ratings[i - 1]) {
				candies[i] = candies[i - 1] + 1;
			} else {
				candies[i] = 1;
			}
		}
		int sum = candies[ratings.length - 1];
		for (int i = ratings.length - 2; i >= 0; i--) {
			if (ratings[i] > ratings[i + 1]) {
				candies[i] = Math.max(candies[i], candies[i + 1] + 1);
			}
			sum += candies[i];
		}
		return sum;
	}

	public static void main(String[] args) {
		int[] candy = new int[] { 4, 2, 3, 4, 1 };
		System.out.println(candy(candy));
	}


拓展学习:Java科普之加密算法

其他有趣的算法:


如赛马问题,25匹马,5个赛道,如何在不用工具的情况下,找到最快的5匹。问题可以简化为3匹马,3个赛道。
分A B C三组马,各赛一场,结果如下:
A1 A2 A3
B1 B2 B3
C1 C2 C3
3场第1名赛一场,得出第1名
如果是A1,则A2跟B1和C1比1场,其他同理,找出第2名
如果是B1,则A2跟B2和C1比1场,其他同理,找出第3名
比赛结束,共需要6场
同理可算出,25匹马需要10场。


如运煤问题,3000吨煤,用载重1000吨的火车,从原点运往终点,路程1000公里,每公里消耗1吨煤,到终点时煤剩几何?
粗略一算,第一种方案:
第一轮,
第1次,先拉1000吨到A,卸下500吨,返回,行程250公里
第2次,再拉1000吨到A,卸下500吨,返回,行程250公里,同理第三次
第3次后,A地剩下1500吨煤,行程250公里
第二轮
继续第4次,同上,到B地行程187.5公里,每次卸下375吨货物
两轮后,行程437.5公里,剩下货物750吨
第三轮
一次性运到,共剩余312.5吨
分析:由于第三轮每次只运750吨,运量未满,导致最终运送较少。
粗略一算,第二种方案:
第1次,先拉1000吨到A, 卸下500吨 行程250公里 ,返回
第2次,再拉1000吨到A,加上250吨满载, 剩下250吨;走250公里到B, 卸下250吨,总行程250公里,返回
第3次,再拉1000吨到A,加上250吨满载;再走250公里到B,加上前两次剩下的共500吨,满载1000吨继续
直行到终点,共剩余 500吨
分析:似乎比较完美,每次都是满载。
粗略一算,第三种方案:
变下思路,将此题变成n千吨煤,可以走多少公里,即消耗多少
那么1000吨走1000公里,2000吨由于中间要折回+第1次向前走共3次即1000*(1+1/3)公里,同理可得3000吨走
1000*(1+1/3+1/5)公里,n千吨可走1000*(1+1/3+1/5+……+1/(2n-1))公里
那么3000公里剩余多少呢?前两句已经讲了3000吨可走的公里,每公里1吨,多出多少公里即多出多少吨
即1000*(1+1/3+1/5)-1000=1600/3吨,即 533.33吨。功夫不负有心人,这就是最终答案!


再如 扔鸡蛋问题,100层楼,2个蛋,n层楼以下扔下不碎,以上碎,问要扔几次才能确认
则声明有x次机会,则最多可能尝试的总楼层数为,x+(x-1)+(x-2)+……+1=x*(x-1)/2
如果100层,则判断小于100即可,结果呢为为14,即 至少要扔14次(则从14层开始扔)


目录
相关文章
|
11月前
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
6月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
1531 35
|
11月前
|
存储 缓存 监控
上网行为监控系统剖析:基于 Java LinkedHashMap 算法的时间序列追踪机制探究
数字化办公蓬勃发展的背景下,上网行为监控系统已成为企业维护信息安全、提升工作效能的关键手段。该系统需实时记录并深入分析员工的网络访问行为,如何高效存储和管理这些处于动态变化中的数据,便成为亟待解决的核心问题。Java 语言中的LinkedHashMap数据结构,凭借其独有的有序性特征以及可灵活配置的淘汰策略,为上网行为监控系统提供了一种兼顾性能与功能需求的数据管理方案。本文将对LinkedHashMap在上网行为监控系统中的应用原理、实现路径及其应用价值展开深入探究。
256 3
|
11月前
|
人工智能 算法 NoSQL
LRU算法的Java实现
LRU(Least Recently Used)算法用于淘汰最近最少使用的数据,常应用于内存管理策略中。在Redis中,通过`maxmemory-policy`配置实现不同淘汰策略,如`allkeys-lru`和`volatile-lru`等,采用采样方式近似LRU以优化性能。Java中可通过`LinkedHashMap`轻松实现LRUCache,利用其`accessOrder`特性和`removeEldestEntry`方法完成缓存淘汰逻辑,代码简洁高效。
521 0
|
6月前
|
存储 算法 搜索推荐
《数据之美》:Java数据结构与算法精要
本系列深入探讨数据结构与算法的核心原理及Java实现,涵盖线性与非线性结构、常用算法分类、复杂度分析及集合框架应用,助你提升程序效率,掌握编程底层逻辑。
|
6月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
10月前
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
696 58
|
9月前
|
机器学习/深度学习 算法 Java
Java实现林火蔓延路径算法
记录正在进行的森林防火项目中林火蔓延功能,本篇文章可以较好的实现森林防火蔓延,但还存在很多不足,如:很多参数只能使用默认值,所以蔓延范围仅供参考。(如果底层设备获取的数据充足,那当我没说)。注:因林火蔓延涉及因素太多,如静可燃物载量、矿质阻尼系数等存在估值,所以得出的结果仅供参考。
372 5
|
9月前
|
存储 负载均衡 算法
我们来说一说 Java 的一致性 Hash 算法
我是小假 期待与你的下一次相遇 ~
476 1
|
8月前
|
运维 监控 算法
基于 Java 滑动窗口算法的局域网内部监控软件流量异常检测技术研究
本文探讨了滑动窗口算法在局域网流量监控中的应用,分析其在实时性、资源控制和多维分析等方面的优势,并提出优化策略,结合Java编程实现高效流量异常检测。
335 0
下一篇
开通oss服务