简单排序算法及异或运算

1. 时间复杂度的注意事项:当时间复杂度相同,要实际进行操作才能比较,因为算法的常数执行时间是不同的。

简单排序算法:(这几种排序算法都不受数据状态的影响)

(一)选择排序:从0位置开始,找到最小(最大)值与0位置元素交换;从1位置开始往后找剩下元素中最大(最小)元素与1位置元素交换,直到倒数第二个元素以后找出最小(最大)交换以后有序。

 /**
     * 选择排序
     */
    public static void selectSort(int[] arr){
        int len = arr.length;
        if(arr == null || len < 2) return;
        int minIndex = 0;
        int i, j;
        for(i = 0; i < len - 1; i++){ //i : 0~len-2
            minIndex = i;//每轮找最小之前,把最小位置重置为i的位置
            for(j = i; j < len; j++){//j : i~len-1找最小(从i开始)
                minIndex = arr[minIndex] < arr[j] ? minIndex : j;
            }
            swap(arr, i, minIndex);
        }
    }

(二)插入排序:将待排序的元素插入前面的有序数列中,以第一个元素为有序序列,将第二个元素插入其中,具体的插入方式是将待排序元素从后向前依次与前面有序元素比较,如果前面有序元素比该元素大(小),交换,直到满足条件为止

/**
     * 插入排序
     */
    public static void insertSort(int[] arr){
        for(int i = 1; i < arr.length; i++){//认为0位置有序,给1~len-1的元素插入排序
            for(int j = i - 1; j >= 0 && arr[j] < arr[j + 1]; j--){
                swap(arr, j, j+1);
            }
        }
    }

(三)冒泡排序:从第一个元素开始,把最大(最小)的元素冒到数列尾部,使用的方法是相邻遇到更大(更小)的,交换。

/**
     * 冒泡排序
     */
    public static void bubbleSort(int[] arr){
        if(arr == null || arr.length < 2) return;
        for(int i = 0; i < arr.length - 1; i++){ //一共走n-1趟
            for(int j = 0; j < arr.length - i - 1; j++){ //从0开始向外冒,直到(n-i-1)的位置,因为后面的i个已经排好了
                if(arr[j + 1] < arr[j]){
                    swap(arr, j, j + 1);
                }
            }
        }
    }

异或运算

(1)^:相同为0,不同为1;也可以看成是无进位相加;结果只与参与异或运算数的个数有关,与顺序无关。

(2)性质:0^N=N;N^N=0;满足交换律和结合律;同一堆数异或与数的先后无关

(3)异或运算交换a,b的前提是a,b不在同一内存,在数组中的体现就是 i != j,否则 arr[i] = arr[j]

arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];

相关题目:

package record1;

public class XorPra {
    /**
     * 题目描述:有一个整型数组,里面有一堆数
     * (1)存在一种数在数组中出现了奇数次,其余数出现了偶数次
     * (2)存在两种数在数组中出现了奇数次,其余数出现了偶数次
     *
     * 分别求解(1)(2)中出现奇数次的数
     * @param args
     */
    public static void main(String[] args) {
        int[] arr = new int[]{1,1,1,2,1,3,3,4,4,4,4,5,5};
//        pro1(arr);

        int[] arr1 = new int[]{1,1,1,2,1,3,3,4,4,4,4,5,5,6};
        pro2(arr1);
    }

    public static void pro1(int[] arr){
        int result = 0;
        for(int i = 0; i < arr.length; i++){
            result = result ^ arr[i];
        }
        System.out.println(result);
    }

    public static void pro2(int[] arr){
        int eor = 0;
        for(int i = 0; i < arr.length; i++){
            eor ^= arr[i];
        } //最后的eor等于a^b
        int diff = eor & (~ eor + 1); //求取某个数最右边的1,(本题中是找出a与b不相同的最右边的一位)
        int a = 0;
        for(int i : arr){
            if((diff & i) == 0) //按照不同的一位将所有数分为两组,如果i是diff位上是0的数
                a ^= i; //因为分组后,该位上为0的数偶数个仍然会被异或掉,只剩下一个奇数个的数
        }
        int b = eor ^ a;
        System.out.println(a + ", " + b);
    }
}

 注:使用&运算来判断某一位上是0还是1;得到某个数最右边的1方法:x & (~x + 1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值