算法(1)

算法

1、算法的评价指标–时间复杂度
时间复杂度: 算法流程中,最差常数操作数量的指标,用O表示 ,读作big O 某某。
计算出常数操作数量的表达式中后,只要n^2,不要n或常数(低阶)
[ 常数操作:一个操作与数据量无关,每次都是固定时间内完成的操作,叫做常数操作。]
I、在一个有序的序列中查找某一数值
解决办法:二分法 时间复杂度O(nlog n)
II、在一个有序的序列(list1)中查找另一序列(list2)中不存在的数值并打印
解决办法:首先将list2进行排序;
对两个序列分别设置一个指向头部的指针p1,p2,比较两个值,若p1>p2时,则p2++;若p1=p2时,则p1++,p2++;若p1<p2,则p1打印并p1++(list1中存在但是list2中不存在)
时间复杂度O(M+N)
III、对一个序列进行排序
解决办法:快速排序 时间复杂度O(nolgn)

题目:在有序的list1中(n个数)查找list2中(m个数)不存在的数并进行打印
解决办法1:list1中每一个数都和list2中每一个数进行对比,则时间复杂度是O(mn)
解决办法2:list1中的数都通过二分的方式与list2中每一个数进行对比,则时间复杂度是O(m
logn)
解决办法3:首先list2先进行排序操作,然后再对两个序列分别设置一个指向头部的指针p1,p2,比较两个值,若p1>p2时,则p2++;若p1=p2时,则p1++,p2++;若p1<p2,则p1打印并p1++(list1中存在但是list2中不存在) ,则时间复杂度是O(m*logm)+O(m+n)

2、排序
冒泡排序 时间复杂度O(n^2) 额外空间复杂度O(1)
7 5 4 3 6 2 1 0
(从0开始一个一个对比,每次获得一个数列中最大值,冒泡到最后;直到排序完成)
第一次排序:【5 4 3 6 2 1 0】7
第二次排序:【4 3 5 2 1 0】6 7
第三次排序:【3 4 2 1 0】5 6 7
第四次排序:【3 2 1 0】4 5 6 7
第五次排序:【2 1 0】3 4 5 6 7
第六次排序:【1 0】2 3 4 5 6 7
第七次排序:【0】1 2 3 4 5 6 7
结束

选择排序 时间复杂度O(n^2) 额外空间复杂度O(1)
(0-n-1选择一个最小的放在0位置,1-n-1选择一个最小的放到1位置,……,直到排序完成)
7 5 4 3 6 2 1 0
第一次排序:0【7 5 4 3 6 2 1】
第二次排序:0 1【7 5 4 3 6 2】
第三次排序:0 1 2【7 5 4 3 6】
第四次排序:0 1 2 3【7 5 4 6】
第五次排序:0 1 2 3 4【7 5 6】
第六次排序:0 1 2 3 4 5【7 6】
第七次排序:0 1 2 3 4 5 6【7】
结束

插入排序 时间复杂度O(n^2) 额外空间复杂度O(1) 复杂度与数组中数字的排列有关系
有序最好O(n) 无序最差O(n^2)
(0-0排序;0-1排序;0-2排序2与1比较,若交换,再1与0比较;0-3排序从后往前比较,插入到适当的位置,……,直到排序完成)
7 5 4 3 6 2 1 0
第一次排序:7【5 4 3 6 2 1 0】
第二次排序:5 7【4 3 6 2 1 0】
第三次排序:4 5 7【3 6 2 1 0】
第四次排序:3 4 5 7【6 2 1 0】
第五次排序:3 4 5 6 7【2 1 0】
第六次排序:2 3 4 5 6 7【1 0】
第七次排序:1 2 3 4 5 6 7【0】
第八次排序:0 1 2 3 4 5 6 7
结束

对数器:
优点:
1> case验证
2> 找出大数据的case出错的原因
3> 贪心策略
步骤:
1、现在有一个你想要测试其正确性的方法a
2、写或使用现有的一个绝对正确但是复杂度不是很好的方法b(同样实现方法a的功能)
3、实现一个随机样本产生器 产生随机的数Math.random()
4、实现a,b方法的对比(isEqual)
5、将a,b对比很多次来验证方法a是否正确
6、若有一个样本使得对比出错,则打印样本分析是哪个方法出错
7、当样本数量很多时,对比测试依然正确,可以确定方法a已经正确。

******测试数组、二叉树、堆、字符串随机发生器

递归
归档(将所有信息压入系统栈:执行到几行+所有变量、参数的值),调用子过程

归并排序 时间复杂度O() 额外空间复杂度O(n)
(将数组分为二部分,然后对两侧进行排序,排序后的设置两个指针,并增加一个辅助数组用来存储排好序的数据,比较指针对应的两个值,小的存入辅助数组,并向后移动,直到其中有一个数组为空或都为空;若其中一个为空,则将两一个直接全部存入辅助数据并返回即可)
T(N) = aT(n/2)+O(N) 时间复杂度O(N*logN)

归并排序的应用
小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
方法一:每个位置的左边都遍历一下 时间复杂度O(N^2)
方法二:归并排序
还是先将数组分成两部分,左侧比右侧小的累加到res中;然后再细分的左侧比右侧小的累加到res,……,直到数组都全部排序完成为止。

public class Test{
	public static int mergerSort(int[] a,int left,int right){
		//判断左边比右边小的话,返回左边的数值进行累加;
		if(left == right)
			return 0;
		int mid = left + (right-left)/2; 
		return mergeSort(a,left,mid)+mergeSort(a,mid+1.right)+merge(a,left,mid,right);
	}
	public static int merge(int[] a,int left,int mid,int right){
		int i,j;
		int index = 0;   //辅助数组下标索引
		int[] temp = new int[right-left+1];//辅助数组
		int res = 0;		//结果
		while(i <= mid && j <= right){
			res += a[i]<a[j]?(right-j+1)*a[i]:0;
			temp[index++] = a[i]>a[j]?a[j]:a[i];
		}
		while(i <= mid){
			temp[index++] = a[i++];
		}
		while(j <= right){
			temp[index++] = a[j++];
		}
		return res;
	}
}

容易溢出:
mid = (left+right)/2
不会溢出的两种写法:
mid = left +(right-left)/2
mid = left + (right-left)>>1

逆序对问题
在一个数组中,左边的数如果比右边的数大,则这两个数构成一个逆序对,请打印所有逆序对。
同上面的思想类似:
也是将数组先分割成两部分,然后每一部分比较并打印逆序对;然后再判断左右两个部分大小,打印逆序对;……,直到指向同一个数值 返回逆序对数为0即止。

public class Test{
	public static void reverseSequence(int[] a,int left,int right){
		if(left == right)
			return;
		int mid = left + (right-left)>>1;
		reverseSequence(a,left,mid);
		reverseSequence(a,mid+1,right);
		printSequence(a,left,mid,right);
	}

	public static void printSequence(int[] a,int left,int mid,int right){
		int i,j;
		int index = 0;
		int[] temp = new int[right - left +1];
		while(i <= mid && j <= right){
			if(a[i] < a[j]){
				int t = j;
				while(t < right){
					System.out.println("逆序对:"+a[i]+","+a[t]);
				}
				temp[index++] = a[i++];
			}
			else
				temp[index++] = a[j++];
		}

		while(i <= mid)
			temp[index++] = a[i++];
		while(j <= right)
			temp[index++] = a[j++];
			
		for(int k = 0;k < temp.length;k++){
			a[left+k] = temp[k];
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值