1、排序算法
1)快速排序
public void qsout(int[] arr,int l,int r){
if(l >= r)
return;
int i,j,temp,t;
i = l;
j = r;
temp = arr[l];
while(i != j){
while(arr[j] >= temp && i < j)
j--;
while(arr[i] <= temp && i < j)
i++;
if(i < j){
t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
arr[l] = arr[i];
arr[i] = temp;
qsort(arr,l,i-1);
qsout(arr,i+1,r);
}
2)归并排序
- 正常归并排序
public void merge_sort(int[] arr,int l,int r,int[] temp){ //这里的temp数组是与原数组的长度一样的空数组
if(l >= r)
return;
int mid = l + r >> 1;
merge_sort(arr,l,mid,temp);
merge_sort(arr,mid+1,r,temp);
int i = l,j = mid+1,k = 0;
while(i <= mid && j <= r){
if(a[i] <= a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
}
while(i <= mid)
temp[k++] = a[i++];
while(j <= r)
temp[k++] = a[j++];
for(i = l,j=0;i <= r;i++,j++)
a[i] = temp[j];
}
- 利用归并排序的特点求逆序对
//求逆序对
public void merge_sort(int[] a,int l,int r,int[] temp){
if(l >= r)
return;
int mid = l + r >> 1;
merge_sort(a,l,mid,temp);
merge_sort(a,mid+1,r,temp);
int k = 0,i = l,j = mid + 1; //两个指针,和一个k用于储存结果
while(i <= mid && j <= r){
if(a[i] <= a[j])
temp[k ++] = a[i ++];
else {
//体现分治思想
//就是:当进入这个条件时,说明,右侧的 < 左侧,符合逆序的条件 因此,右侧的这个数,与左侧剩余数构成逆序数对
//经验:分析分治时,直接用随机的数据来判断
//eg: 1 2 3 5 6 78 9 与 4 67 879 889 999
count += mid - i + 1;
temp[k++] = a[j++];
}
}
while(i <= mid)
temp[k ++] = a[i ++];
while(j <= r)
temp[k ++] = a[j ++];
for(i = l,j = 0;i <= r;i++,j++)
a[i] = temp[j];
}
2、查找算法
1)二分查找
- 简单二分查找
public int findIndex(int[] arr,int x){
int l = 0,r = arr.length-1;
while(l < r){
int mid = l + r >> 1;
if(arr[mid] >= x)
r = mid;
else
l = mid + 1;
}
return arr[r] == x ? r : -1;
}
2)二分查找第一个或最后一个出现的目标值
- 查找目标值出现的第一个位置
//二分查找第一次出现的目标数字
public static int FindF(int x,int[] a){
if(a.length == 0)
return -1; //数组为空
int l = 0,r = a.length-1;
while(l < r){
int mid = l + r >> 1;
if(a[mid] > x)
r = mid - 1; //不包含左端点 因为将a[mid] = x 单独拉出来了,可以判断左端点(保证 r与l相等)
else if(a[mid] == x)
r = mid;
else
l = mid + 1;
}
return a[l] == x ? l : -1; //如果数组只有两个元素,则 r 与 l 不同,此时 r 是正确的值,r 是 -1,因此用 l
//如果数组元素大于两个元素,则 l == r
}
- 查找目标值出现的最后一个位置
//二分查找最后一次出现的目标数字
public static int FindL(int x,int[] a){
if(a.length == 0)
return -1; //数组为空
int l = 0,r = a.length-1;
while(l < r){
int mid = l + r + 1 >> 1; //由于的当r=mid-1时,r与l的值不相等,因此在这里 + 1 保证l与r的值相等
if(a[mid] > x)
r = mid - 1; //不包含左端点 因为将a[mid] = x 单独拉出来了,可以判断左端点(保证 r与l相等)
else if(a[mid] == x)
l = mid;
else
l = mid + 1;
}
return a[r] == x ? r : -1; //如果数组只有两个元素,则 r 与 l 不同,此时 r 是正确的值,l 是 -1,因此用 r
//如果数组元素大于两个元素,则 l == r
}
- 查找出现的峰值
public static int FindMax(int[] a){ //查的是其中一个最大值 1,2,1 是 2 的索引 ,1,2,3 是 3 的索引
int l = 0, r = a.length-1;
while(l < r){
int mid = l + r >> 1;
if(a[mid] > a[mid + 1] && mid != 0 && a[mid] > a[mid - 1] )
return mid;
else if (a[mid] > a[mid + 1]) {
r = mid;
} else if (mid != 0 && a[mid] > a[mid - 1]) {
l = mid+1;
} else {
r = mid;
}
}
if(a.length == 1)
return 0;
if(a[0] > a[1])
return 0;
return a.length-1;
}