分治法之排序及二分查找

1、n个数的全排列问题。

代码


public class one {
    // 交换函数
    public static void swap(char[] array, int i, int j) {
        char temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    // 全排列函数
    public static void fun(char[] array, int p) {
        if (p == array.length) { //当前为最后一个元素的排列,及当前序列已经完整
            System.out.println(new String(array));
        } else { // 进行全排列模拟
            for (int i = p; i < array.length; i++) { // 分别确定一种字符串的i到位
                swap(array, p, i);
                fun(array, p + 1);
                swap(array, i, p);
            }

        }

    }

    public static void main(String args[]) {
        String string = "123";
        fun(string.toCharArray(),0);

    }
}

输出结果

测试固定序列串 “123” 的全排列结果,共输出对应的6种排列结果。
image.png

总结

该算法优点:简洁、容易实现
缺点:没有排序效果。解决办法:可以存储排列后的每一种结果,然后对结果的序列数组进行排序,从而解决没有排序的问题,但是随着待排数组的增长其排序的时间复杂度也会不断上升。故该算法不适合解决长序列的全排列排序问题。

2、在一个给定的n个元素的有序序列中查找出与给定关键字x相同的元素的具体位置。即输入一个n个元素的序列,其中n个元素从小到大的顺序排列,查找是否存在给定的值x.(用二分查找法)。

代码

import java.util.Scanner;

public class two {
    public static int BinarySearch(int[] array, int x) {
        int l = 0, r = array.length;
        // 二分查找
        while (l <= r) {
            int mid = (l + r) / 2;
            if (array[mid] > x) {
                r = mid;
                l = l + 1;
            } else if (array[mid] < x) {
                l = mid;
                r = r - 1;
            }else{  // 找到该元素,返回该元素的位置
                return mid+1;
            }
        }
        return -1;
    }

    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        int n;
        n = scanner.nextInt();
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = scanner.nextInt();
        }
        int x = scanner.nextInt();
        int p = BinarySearch(array,x);
        System.out.println(p);
    }
}

输出结果

测试用例1
输入

6
1 2 3 4 5 6
9

输出(-1代表未找到)

-1

测试用例1
输入

6
1 2 3 4 5 6
5

输出(-1代表未找到)

5

总结

二分搜索中在x值大于中间值的情况下,需要进行l=mid,r=r-1操作;在x值小于中间值的情况下,要进行r=mid,l=l+1的操作;

3、改写二分搜索算法:

设a[0:n-1]是已排好序的数组,请改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j。当搜索元素在数组中时,i和j相同,均为x在数组中的位置。

代码

import java.util.Scanner;

public class Three {
    public static int BinarySearch(int[] array, int x) {
        int l = 0, r = array.length;
        int mid = -1;
        if(x > array[array.length-1]){  //当前x值已经大于所有数组中的元素
            return array.length;
        }
        if(x < array[0]){  //当前x值已经小于所有数组中的元素
            return 0;
        }
        // 二分查找
        while (l <= r) {
            mid = (l + r) / 2;
            if (array[mid] > x) {
                r = mid-1;
            } else if (array[mid] < x) {
                l = mid+1;
            } else {  // 找到该元素,返回该元素的位置
                return mid + 1;
            }
        }
        return mid;
    }

    public static void main(String args[]) {
        Scanner scanner = new Scanner(System.in);
        int n;
        n = scanner.nextInt();
        int[] array = new int[n];
        for (int i = 0; i < n; i++) {
            array[i] = scanner.nextInt();
        }
        int x = scanner.nextInt();
        int p = BinarySearch(array, x);
//        System.out.println(p);
        if (p!=0&&array[p-1] == x) { //当前是找到该x值
            System.out.println("在有序数组中找到该值位置为" + p);
        }else{ // 未找到该值
            if(p==array.length){  //如果比所有与元素都大则不存在比他大的最小值
                System.out.println("在有序数组中未找到该值,但存在比其小的最大元素:"+array[p-1]);
            }else if(p==0){ //如果比所有与元素都小则不存在比他大的最小值
                System.out.println("在有序数组中未找到该值,但存在比其大的最小元素:" + array[0]);
            }else{
                System.out.println("在有序数组中未找到该值,但存在比其大的最小元素:" + array[p]+",存在比其大的最小元素:"+array[p-1]);
            }

        }
    }
}


输出结果

image.png
image.png
image.png

总结

二分法关键代码

 // 二分查找
        int l = 0, r = array.length;
        int mid = -1;
        while (l <= r) {
            mid = (l + r) / 2;
            if (array[mid] > x) {
                r = mid-1;
            } else if (array[mid] < x) {
                l = mid+1;
            } else {  // 找到该元素,返回该元素的位置
                return mid + 1;
            }
        }
        return mid;
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦码城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值