时间复杂度O(N^2):太简单没啥要解释的了
额外空间复杂度O(1):在完成每个目标的过程中,在目标完成过程中增加的变量和对象占用的空间
递归的深入剖析
通过一个简单实例来分析:通过递归求一个数组中的最大值
public class GetMaxNum {
public static int getMax(int[] arr,int L,int R){
if (L==R){
return arr[L];
}
int middle=(L+R)/2;
int leftMax=getMax(arr,L,middle-1);
int rightMax=getMax(arr,middle,R);
return Math.max(leftMax,rightMax);
}
}
接下来我们分析递归的底层是怎么实现的
递归的过程就是一个系统进行一个压栈的过程
从底层一路压栈上去,当到达了if判断的结束之后,系统就会进行一个出栈的过程,一步步往回出栈。
总结来说:在逻辑上是自己调用自己,在系统中只是一个系统栈而已。所以说所有的递归都可以变成非递归,也就是迭代。
master公式的详细讲解
T:时间复杂度
N:样本量
以上面为例:
T(N)=a*T(N/b)+O(N^d) --》 T(N)=2*T(N/2)+O(N^0)
T(N):指的是该算法完成某个目标所使用的所有时间;
2*T(N/2):上面程序将查询分为左右两边,也就是将样本平分了(N/2),又因为被平分了两半所以就要乘以2 ( 2*T(N/2) ),
O(N^0):主查询块以外的一些消耗,这里就是左右两边对比的消耗,只进行了一次比较所以N^d=1,也就是d=0
然后带入式子:
log(b,a):以b为底,log a
log(b,a) >d --》 log(2,2) > 0 满足了第一个,所以上面式子的复杂度就是O(N^log(2,2)) --》 O(N)
归并排序的深入讲解
时间复杂度O(N*logN),额外空间复杂度O(N)
思想:
假设:有一个无序数组:arr=5 3 6 2 0 1
首先将左边排好序,和右边排好序
然后创建一个空数组,对原数组左右两边进行比较:
首先比较a和b值:a>b
放入到空数组中:
移动b位置
继续比较a和b的值:a>b
移动b位置
继续比较a和b的值:a>b
移动b位置,发现b已经没有了,直接拷贝a的数组
排序完成!
使用master公式计算:T(N)=2T(N/2)+O(N)
log(b,a)=d,所以复杂度是N*log(N)
Coding:
将左右两边分别排好序
merge()方法
while语句中:排序的过程,如上面分析一样,比较两个p1和p2的值,然后赋值以及移动
上面while语句一定会导致一个越界,这样的话,就需要将另外一个没有越界的值赋到后面
完整代码
package cn.mxl.work;
public class MergeSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr= {4,3,2,7,6,8,0,9};
sortProcess(arr, 0, arr.length-1);
for(int i : arr) {
System.out.println(i);
}
}
public static void sortProcess(int[] arr,int L,int R) {
if(L == R) {
return ;
}
int mid=L+((R-L)>>1);
sortProcess(arr,L,mid);
sortProcess(arr,mid+1,R);
merge(arr,L,mid,R);
}
private static void merge(int[] arr, int L, int mid, int R) {
// TODO Auto-generated method stu
int[] help=new int[R-L+1];
int i=0;
int p1=L;
int p2=mid+1;
while(p1<=mid&&p2<=R) {
help[i++]=arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
}
// 两个必有且只有一个越界
while(p1<=mid) {
help[i++]=arr[p1++];
}
while(p2<=R) {
help[i++]=arr[p2++];
}
for(i=0;i<help.length;i++) {
arr[L+i]=help[i];
}
}
}
归并解决小和问题
问题描述:
左右两边进行分治 ,将左边和右边分别排好顺序
左边的每个数字对于右边排好序的来说,当前值要被加(右边的长度-p2位置+1)次
完整代码:
public class SmallSum {
public static int partitionSort(int[] arr,int L,int R){
if (L==R){
return 0;
}
int middle=L+((R-L)>>1);
return partitionSort(arr,L,middle)
+partitionSort(arr,middle+1,R)
+merge(arr,L,middle,R);
}
private static int merge(int[] arr, int l, int middle, int r) {
int pos1=l;
int pos2=middle+1;
int[] help=new int[r-l+1];
int i=0;
int res=0;
while (pos1<=middle && pos2<=r){
res+=arr[pos1]<arr[pos2]?(r-pos2+1)*arr[pos1]:0;
help[i++]=arr[pos1]<arr[pos2]?arr[pos1++]:arr[pos2++];
}
while (pos1<=middle){
help[i++]=arr[pos1++];
}
while ((pos2<=r)){
help[i++]=arr[pos2++];
}
for (int j = 0; j < help.length; j++) {
arr[l+j]=help[j];
}
return res;
}
public static void main(String[] args){
int[] arr={1,3,4,2,5};
int res = partitionSort(arr, 0, arr.length - 1);
System.out.println(res);
}
}