算法知识-排序、二分查找

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;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值