目录
查找最大值
利用二分查找通过递归来找最大值
首先将数组通过中间元素arr[mid]将数组分为两个部分,两个部分分别递归,直到找到最大值
本质是一个多叉树,在计算树的所有的节点的时候,利用栈玩了一个后序遍历,每一个节点都通过自己的子节点给自己汇总信息之后才能够继续向上返回,栈空间就是整棵树的高度只需要在一个高度上进行压栈,这就是一个递归的过程
代码
public class Code6_getMax { public static int getMax(int[] arr) { return process(arr,0,arr.length-1); }//master公式 public static int process(int[] arr,int l,int r){ if(arr.length==1){ return arr[l]; } int mid=l+((r-l)>>1); int lMax= process(arr,l,mid); int rMax=process(arr,mid+1,r); return Math.max(lMax,rMax); } }
master公式
只要满足子问题具有相同规模的递归都可以用master公式
总结
归并排序O(nlgn)
可以运用master公式来求解
左边先排好序,右边先排好序,左右merge在一起,整体就有序了
每一次的比较行为没有被浪费,每次比较最后会变成一个新的有序的数组,这种变成了有序的的东西,信息是往下传递的,正式因为这样它变成了O(n*lgn)
代码
public class Code7_mergeSort {
public static void mergeSort(int[] arr){
if(arr.length<2||arr==null){
return ;
}
process(arr,0,arr.length);
}
public static void process(int[] arr,int l ,int r){
if(l==r){
return ;
}
int mid=l+((r-l)>>1);
process(arr,l,mid);
process(arr,mid+1,r);
merge(arr,l,mid,r);
}
public static void merge(int[] arr,int l,int mid,int r){
//左边已经有序,右边已经有序,通过merge使两边同时有序
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(int ii=0;ii<help.length;ii++){
arr[l+ii]=help[ii];
}
}
}
小和问题
1 3 4 2 5
1的左边没有比1小的数,所以小和为零
3的左边有1,所以小和是1
4的左边有3和1 ,所以小和是4
2的左边是1,小和是1
5的左边是1 3 4 2 所以小和是10
所以整个数组的小和是16
暴力解决很轻松,两层for循环就解决了,只不过时间复杂度是O(n2)
我们可以换一种思路来解决这个问题
看被查看的数字的右边有几个比他大的,有几个就算这个出现几次小和
如 1 出现的次数是4次
3出现的次数是2次
4出现的次数是1次
2出现的次数是1次
5出现的次数是0次
加起来也是16
所以这个可以用归并排序来进行解决
又与归并排序有一点不同,当左边的数等于右边的数的时候将左边的数放进外排序的数组里面,如果不这样做,就会不知道右边有多少个数比左边与右边相等的那个数大
代码
public class Code8_SmallSum {
public static int smallSum(int[] arr){
if(arr.length==0||arr==null){
return 0;
}
return mergeSort(arr,0,arr.length-1);
}
public static int mergeSort(int[] arr,int l,int r){
if(l==r){
return 0;
}
int mid=l+((r-l)>>1);
return mergeSort(arr,l,mid)
+mergeSort(arr,mid+1,r)
+merge(arr,l,mid,r);
}
public static int merge(int[] arr,int l,int mid,int r){
int[] help=new int[r-l+1];
int i=0;
int p1=l;
int p2=mid+1;
int ret=0;
while(p1<=mid&&p2<=r) {
ret += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p2] : 0;
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(int j=0;j<help.length-1;j++){
arr[l+j]=help[j];
}
return ret;
}
}