当前位置:   article > 正文

选择、冒泡、插入排序、二分法、异或应用_冒泡排序与选择排序的时间复杂度与数组的初始状态无关

冒泡排序与选择排序的时间复杂度与数组的初始状态无关

1、选择排序和冒泡排序的时间复杂度(O(N^2))和数据初始状态无关,无论逆序,正序,或其他此序,操作流程相同

package learn;

public class Demo {
    public static void main(String args[]){
        int arr[]={9,8,7,6,5};
        //selectionSort(arr);
        bubbleSort(arr);
        print(arr);
    }

    //选择排序
    public static void selectionSort(int arr[]){
        if(arr==null || arr.length<2)return;//数组arr不指向任何对象和长度为0/1的数组无需排序
        for(int i=0;i<arr.length-1;i++){
            int minIndex=i;
            for(int j=i+1;j<arr.length;j++){//j=i+1<arr.length ->i<arr.length-1
                if(arr[j]<arr[minIndex]){//minIndex=arr[j]<arr[minIndex]?j:minIndex
                    minIndex=j;
                }
            }
            //if(min!=i)swap(arr[i],arr[minIndex]); 这样写有错,只是单纯交换了两个数的值,数组中的元素未变
            //可以直接在selectionSort函数中交换arr[i],arr[minIndex]。若要用另一个函数,应把arr数组也传过去
            if(i!=minIndex)swap(arr,i,minIndex);
        }
    }

    //冒泡排序
    public static void bubbleSort(int arr[]){
        if(arr==null || arr.length<2)return;
        for(int i=arr.length-1;i>0;i--){
            for(int j=0;j<i;j++){
                if(arr[j]>arr[j+1])swap(arr,j,j+1);
            }
        }
    }

    public static void swap(int arr[],int a,int b) {
//        int x=arr[a];
//        arr[a]=arr[b];
//        arr[b]=x;
        arr[a]=arr[a]^arr[b];
        arr[b]=arr[a]^arr[b];
        arr[a]=arr[a]^arr[b];
    }

    public static void print(int []arr) {
        for(int i=0;i<arr.length;i++){
            System.out.print(arr[i]+" ");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

2、插入排序:
正序:O(n)
逆序:O(n^2)

    public static void insertionSort(int arr[]) {
        if(arr==null || arr.length<2)return;
        for(int i=1;i<arr.length;i++){
            for(int j=i-1;j>=0 && arr[j]>arr[j+1];j--){
                swap(arr,j,j+1);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3、二分法:

(1)在一个有序数组中,找某个数是否存在
注意事项:位运算优先级低于加减 注意加不加括号

    public static boolean exist (int[] arr,int num) {
        if (arr == null || arr.length == 0) return false;
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
            int mid=left+((right-left)>>1);//mid=(left+right)/2 left+right可能超出范围 -> mid=left+(right-left)/2
            //位运算比除运算快
            if(arr[mid]==num){
                return true;//找到即返回,无需再循环
            }else if(arr[mid]>num){
                right=mid-1;
            }else {
                left=mid+1;
            }
        }
        //找到返回,循环结束 或者 left==right 只有一个元素了
        return num==arr[left];//最后一个元素是否等于num
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

循环条件可以变一下

    public static boolean exist (int[] arr,int num) {
        if (arr == null || arr.length == 0) return false;
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            int mid=left+((right-left)>>1);

            //位运算比除运算快
            if(arr[mid]==num){
                return true;//找到即返回,无需再循环
            }else if(arr[mid]>num){
                right=mid-1;
            }else {
                left=mid+1;
            }
        }
        return false;//最后一个数都不等,退出循环
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

(2)在一个有序数组中,找>=某个数最左侧的位置
(3)在一个有序数组中,找<=某个数最右侧的位置

package learn;

public class Demo {
    public static void main(String args[]){
		int arr[]={2,2,3,3,3,4,5,5,6,6,6,6,7,7,7};
        System.out.println(arr.length);
        System.out.println(nearestIndex(arr,3));
    }

    public static int nearestIndex(int[] arr,int num) {
        int left = 0;
        int right = arr.length - 1;
        int index=-1;//记录最左
        while (left <= right) {//等号别漏了,最后一个元素也要判断是否大于等于num,它也有可能是那个最左的
            int mid=left+((right-left)>>1);

            if(arr[mid]>=num){
                index=mid;
                right=mid-1;
            }else {
                left=mid+1;
            }
        }
        return index;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

(4)局部最小值问题

    public static int getLessIndex(int[] arr,int num) {
        if(arr==null || arr.length==0)return -1;
        if(arr.length==1 || arr[0]<arr[1]){
            return 0;//第0位为局部最小值
        }
        if(arr[arr.length-1]<arr[arr.length-2]){
            return arr.length-1;//最后一位为局部最小值
        }
        
        //前面都没有返回的话,说明中间有数比两边都小
        int left=1;
        int right = arr.length - 2;
        int mid=0;
        while (left <right) {
            //循环条件 可以假设只有3个数 left==right 这个数在前面的比较中并未大于第一个数和第三个数 无需在循环中在比较一次 故不用取等
            mid=left+((right-left)>>1);

            if(arr[mid]>arr[mid-1]){
                right=mid-1;
            }else if(arr[mid]>arr[mid+1]){
                left=mid+1;
            }else {
                return mid;
            }
        }
        return left;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

5、利用异或:
题目:一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数

    public static void findOne(int[] arr) {
        int eor=0;
        for(int i=0;i<arr.length;i++){
            eor^=arr[i];
        }
        System.out.println(eor);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

题目:一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数

    public static void findOne(int[] arr) {
        int eor=0;
        for(int i=0;i<arr.length;i++){
            eor^=arr[i];
        }
        //eor==a^b;
        //a!=b -> eor至少有一个1
        int rightOne=eor&(~eor+1);//提取eor最右侧的1
        //说明此位 要么a为0,b为1 要么a为1,b为0
        int x=0;
        for(int i=0;i<arr.length;i++){
            if((rightOne & arr[i])!=0){//找到和eor最右侧1 同一位置为1的arr中的数
                x^=arr[i];//因为arr中同一位置为1的其他数都出现偶数次,异或结果为0 故x最终值不是a 就是b
            }
        }
        System.out.println(x+" "+(x^eor));//假设x为a,则a^a^b=b
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

题目:一个数 二进制中 1的个数

    public static void countOne(int n) {
        int rightOne,count=0;
        while(n!=0){
            rightOne=n&((~n)+1);
            count++;
            n^=rightOne;//n-=rightOne 正数可以 负数不行
        }
        System.out.println(count);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/632372
推荐阅读
相关标签
  

闽ICP备14008679号