java程序中的算法1

1. 概述

        所谓的算法,就是计算方法即在进行某种运算时所使用的方式方法,在计算机中的算法指的是,在计算机中进行运算时提前为计算机设定的计算方法。

2. 算法的两个关键指标

2.1 运行时间

2.2 内存消耗

3. 预备知识

3.1 异或运算符^

3.1 特点

异或运算的特点是,一个数据A异对一个数据B异或两次的结果是数据A

例如:

System.out.println(3 ^ 4 ^ 4);

4. 经典的算法题

4.1 题目1

 题目:现有0-99,共计100个整数,各不相同,将这100个数据放入一个数组中,然后,在这个数组中添加一个0-99的任意一个整数数值(唯一重复的数值),把这101个数据随机排列,然后将这个重复的数字找出来。

public static void test01(){
    // 1. 定义数组
	int[] arr = new int[101];
	for(int index = 0 ; index < arr.length ; index ++){
		arr[index] = index;
	}
	// 随机添加一个重复的数据
	arr[100] = new Random().nextInt(99) + 1;
	printArray(arr);
	System.out.println();
	System.out.println("---------------------------------------------");
		
	// 2. 将数组随机排列
	/*
		 异或方式做交换效率较低
	Long start = System.nanoTime();
	for(int i = 0 ; i < 1000 ; i++){
		int index1 = new Random().nextInt(101);
		int index2 = new Random().nextInt(100) + 1;
		arr[index1] = arr[index1] ^ arr[index2];
		arr[index2] = arr[index1] ^ arr[index1];
		arr[index1] = arr[index1] ^ arr[index2];
	}
	Long end = System.nanoTime();
	System.out.println((end - start)); // 3568313
	*/
	Long start1 = System.nanoTime();
	for(int i = 0 ; i < 1000 ; i++){
		int index1 = new Random().nextInt(101);
		int index2 = new Random().nextInt(101);
		int temp = arr[index1];
		arr[index1] = arr[index2];
		arr[index2] = temp;
	}
	Long end1 = System.nanoTime();
	System.out.println((end1 - start1)); // 629969
		
	printArray(arr);
	System.out.println();
		
	// 3. 找出重复的数字
	// 方式一:循环遍历
	// 缺点:思路简单,时间消耗较大
	loop:for(int i = 0 ; i < arr.length; i++){
		for(int j = i + 1 ; j < arr.length ; j++){
			if(arr[i] == arr[j]){
				System.out.println("重复元素是:" + arr[i]);
				break loop;
			}
		}
	}
		
	// 方式二:累加求差
	// 思路:因为数组中的数值为101个整数,且随机之前,前100个为不重复的数据,所以两者求和之差即为重复的数据
	// 缺点:有数据溢出的风险
	int sum = 0 ;
	for(int i = 0 ; i < arr.length ; i ++){
		sum += arr[i];
	}
	for(int i = 0 ; i < 100 ; i ++){
		sum -= i;
	}
	System.out.println("重复元素是:" + sum);
		
	// 方式三:利用异或的特性
	// 思路:拿数组的0号元素和后面的所有元素进行异或,然后用异或的结果再和0-99的数据做异或,最终保留的结果就是重复的元素
	for(int i = 1 ; i < arr.length ; i++){
		arr[0] = arr[0] ^ arr[i];
	}
	for(int i = 0 ; i < 100 ; i ++){
		arr[0] = arr[0] ^ i;
	}
	System.out.println("重复元素是:" + arr[0]);
}
/**
* 打印数组
*/
private static void printArray(int[] arr) {
	int count = 0;
	// 遍历数组
	for(int i = 0 ; i < arr.length ; i ++){
		if(++count%10 == 0){
			System.out.println(arr[i] + "\t");
			continue;
		}
		System.out.print(arr[i] + "\t");
	}
}

4.2 题目二

题目:现有0-99,共计100个整数,各不相同,将这100个整数放到一个数组中随机排列,将其中的任意一个数字替换成0-99另一个数(唯一重复的数字)

问题:将这个重复数字找出来 

public static void test02(){
	int[] arr = new int[100];
	for(int i = 0 ; i < arr.length ; i++){
		arr[i] = i;
	}
	// 设置重复数据
	int i = new Random().nextInt(100);
	int j = new Random().nextInt(100);
	while( i == j){
		i = new Random().nextInt(100);
		j = new Random().nextInt(100);
	}
	arr[i] = arr[j];
	System.out.println("重复的元素是:" + arr[i]);
		
	// 方式一:循环遍历
	loop:for(int index = 0 ; index < arr.length ; index ++){
		for(int inner = index + 1 ; inner < arr.length ; inner ++){
			if(arr[index] == arr[inner]){
				System.out.println("重复元素是:" + arr[index]);
				break loop;
			}
		}
	}
		
	// 方式二:新建一个数组来实现,用空间换时间
	// 思路:新建一个数组,让其长度等于旧的数组,并让其值都等于0,然后,拿旧数组中的值作为新数组的索引,并将该索引处的值加1
	int[] newArr = new int[arr.length];
	for(int index = 0 ; index < arr.length ; index ++){
		newArr[arr[index]] ++;
		if(newArr[arr[index]] == 2){
			System.out.println("重复元素是:" + arr[index]);
			break;
		}
	}
}

4.3 题目三

题目:把两个int类型的变量交换

public static void test03(){
	int a = 10;
	int b = 20;
		
	// 方式一:临时变量法
	int temp = a;
	a = b;
	b = temp;
	System.out.println("a = " + a + "  b = " + b);
	
	// 方式二:异或方法(时间换空间)
	a = a ^ b;  // a = a ^ b
	b = a ^ b;  // b = a ^ b = a ^ b ^ b = a
	a = a ^ b;  // a = a ^ b = a ^ b ^ a
	System.out.println("a = " + a + "  b = " + b);
	
	// 方式三:加减法
	a = a + b;
	b = a - b;
	a = a - b;
	System.out.println("a = " + a + "  b = " + b);
		
}

注意:这里用异或方式,所耗的时间较多,但是内存消耗比较小。

4.4 裴波那契数列问题

所谓的裴波那契数列指的是这样的一个数列:1、1、2、3、5、8、13、21、34、。。。。。。

求该数列中第30个数据的值。

规律:

        从第三个元素开始,每一个数据是前两个数据的和

        第一个和第二个数据的值是1

4.4.1 递归算法实现

public static void test04(){
	System.out.println(getNum(30));
}
	
// location表示第几个元素
private static int getNum(int location){
	if(location == 1 || location == 2){
		return 1;
	}
	return getNum(location -1 ) + getNum(location - 2);
}

注意:递归算法可以实现,但是,效率太低,因为方法的调用次数过多,会有很多重复调用的情况出现

4.4.2 备忘录算法

        使用递归算法,会出现很多相同参数的调用,这样会严重影响性能,为此,我们可以使用缓存,将相同参数的结果缓存在一个hashMap中,这种暂时存储的方式就叫做备忘录算法实现。

public static void test05(){
	System.out.println(getNumByHash(30));
}
	
private static HashMap<Integer,Integer> hm = new HashMap<Integer,Integer>();
private static int getNumByHash(int location){
	if(location == 1 || location == 2){
		return 1;
	}
	if(hm.containsKey(location)){
		return hm.get(location);
	}else {
		int value = getNumByHash(location - 1) + getNumByHash(location - 2);
		hm.put(location, value);
		return value;
	}
}

4.4.3 动态规划算法

通过分析,我们知道从第三个元素开始,每一个数据是前两个数据的和,我们拿这个和和它前面的数据,又可以得到一个新的数据。

public static void test06(){
	System.out.println(getNum5(30));
}
	
public static int getNum5(int location){
	if(location == 1 || location == 2){
		return 1;
	}
	int a = 1;
	int b = 1;
	int temp = 0 ;
	for(int i = 3 ; i <= location ; i++){
		temp = a + b;
		a = b;
		b = temp;
	}
	return temp;
}
发布了128 篇原创文章 · 获赞 6 · 访问量 3242

猜你喜欢

转载自blog.csdn.net/weixin_43318134/article/details/103440870