认识时间复杂度和异或运算

认识时间复杂度和异或运算

1、时间复杂度:

取最高阶的,当一样的时候就不看时间复杂度了,直接代码运行测试看哪个更快就是时间复杂度更好

时间复杂度一律按照最差时间复杂度进行计算,就跟冒泡排序和选择排序,他们的时间复杂度都是O(n^2) ;但是插入排序如果在数组原本有序的情况下进行插入排序,那么他的时间复杂度是O(n),但是最坏的情况下,就是元素刚好是倒序,那么你要排序,就要都交换一遍;所以最坏的时间复杂度是O(n^2);

2、空间复杂度:

如果是有限的数,那么不需要开额外的空间就是o(1);如果是数组需要开一个跟之前一样的就是O(n)

异或运算:相同为0,不同为1(无进位式相加)

3、异或运算满足的条件:

  1. 其它^a=a a^a=0;
  2. 满足交换律和结合律

可以用于交换两个数

image-20210830153258015

两个数的值一样的话可以使用异或运算 ,但是如果两个数在不同的内存就出现问题了。比如数组中的i位置和j位置可以交换值的前提是i位置的值不等于j位置的值。否则他们会被覆盖为0;因为会以为是自己跟自己异或,就是a^a=0;这个异或运算是地址之间的运算,如果两个都是基本数据类型,那么比较的就是值,如果不是基本数据类型的话比较的就是地址,地址一样就是自己跟自己异或。

4、异或运算例题

1、在数组中,只有一种数出现了奇数次,其它元素都出现了偶次数,那么求这种数出现了几次

答:定义一个中间量a=0;跟数组中每个元素进行异或运算,结果作为下一个元素运行的值和下一个元素进行异或运算。

image-20210830155320473

2、在数组中,有两种数出现了奇数次,其它元素都出现了偶次数,求出现奇数次的元素。

答:

  1. 定义一个中间量eor,假设奇数次的元素是a和b,eor与数组元素进行异或运算,最后结果为a^b。 而a^b不等于0;
  2. 现在如果是二进制形式表示数组元素的值,只要找到一个位置不同那么他们就是不同的数据。奇数次中的如果第八位为1分为一组,为0分为一组,偶次数也一样。那么定义一个eor2;他继续去异或数组中的元素,但是不是全部元素都异或,只要异或第八位是0或者1的就可以了,最后eor2的结果是a or b
  3. 所以eor2的结果可以得出来一个是出现奇数次的元素,另一个是出现奇数次的元素只要用eor^eor2就可以了。

image-20210830161439236

image-20210830161529913

image-20210830163551968

package 左神算法.异或运算;

public class YiHuoYunSuan {
    public static void main(String[] args) {
        int[] arr = {2, 1, 3, 1, 3, 1, 3, 1, 3};
        printOddTimeNum1(arr);
        int[] arr1 = {2, 1, 3, 1, 3, 1, 3, 1};
        printOddTimesNum2(arr1);

    }
    //只有一个数出现奇数次
    public static void printOddTimeNum1(int[] arr) {
        int eor = 0;
        int count = 0;
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == eor) {
                count++;
            }
        }
        System.out.println(eor);
        System.out.println(count);

    }
    //有两个数出现奇数次
    public static void printOddTimesNum2(int[] arr) {
        int eor = 0;
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
//        eor=a^b
//        eor!=0
//        eor必然有一个位置上是1
        int rightOne = eor & (~eor + 1);//提取出最右的1
        int onlyOne = 0;//eor1
        for (int cur : arr) {
            if ((cur & rightOne)==1) {
                onlyOne ^= cur;
            }
        }
        System.out.println(onlyOne + " " + (eor ^ onlyOne));
    }
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值