算法与数据结构笔记(时间复杂啊,选择排序,冒泡排序,插入排序,归并排序,快速排序,堆排序,基数以及计数排序)

这篇博客深入探讨了各种排序算法的时间复杂度,包括插入排序、二分法、归并排序、快速排序、堆排序以及桶排序。通过实例解析了异或运算在寻找数组中出现奇数次的数的应用,讲解了如何使用对数器来验证算法的正确性,并介绍了递归在求解最大值中的应用。此外,博主还详细分析了归并排序和快速排序的优化版本,以及堆结构在排序中的作用。
摘要由CSDN通过智能技术生成

异或运算:不进位相加

1. 时间复杂度

所谓常数操作就是跟数据量无关,是一个固定时间的操作。(加减乘除位运算等等)
冒泡排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2)

评价一个算法流程的好坏,先看时间复杂度的指标,然后再分析不同数据样本下的实际运行时间,也就是“常数项时间”。

两个数交换:
a = a 异或 b
b = a 异或 b
a = a 异或 b

public static void swap(int[] arr,int i, int j){
   
	arr[i] = arr[i]^arr[j];
	arr[j] = arr[i]^arr[j];
	arr[i] = arr[i]^arr[j];
}

// i 不能等于 j,不能是同一个内存区域

1.1 例题01,异或运算

链接43:24
在一个数组中,int[],已知只有一种数出现了奇数次,其他所有数都出现了偶数次,
1.怎么找到出现了奇数次的数?

定义一个int数,eor=0,然后将eor和数组中所有数异或。

2.如果已知有两种数出现了奇数次,其他所有数都出现了偶数次,找出这两个出现了奇数次的数?
时间复杂度O(N),空间复杂度O(1)的方法,

进行第一问的操作,得到eor
eor = a ^ b, eor != 0
将eor中的以最后一个出现1的位上(第n位), 分为两种。
eor’ 与数组继续异或,但是只抑或 数组中第n位只出现1或者0的数

package leetcode;

public class First_0228 {
   
    public static void main(String[] args) {
   
        int[] a = {
   1,1,1,1,5,5,5,5,9};
        int eor = 0;
        for (int i : a) {
   
            eor = eor ^ i;
        }
        System.out.println(eor);
    }

    
}

eor : 1010111100
~eor: 0101000011
~eor+1 : 0101000100
& : 0000000100

 // ~取反 &与, 取出最右侧的1来
        int rightOne = eor_1 & (~eor_1 + 1);
package leetcode;

public class First_0228 {
   
    public static void main(String[] args) {
   
        int[] list = {
   1,1,1,1,5,5,5,5,7,7,7,7,8,9};
        int eor_1 = 0;
        for (int i : list) {
   
            eor_1 = eor_1 ^ i;
            // a!=b eor_1中必有一个位置上为 1
        }
        // ~取反 &与, 取出最右侧的1来
        int rightOne = eor_1 & (~eor_1 + 1);
        int onlyOne = 0; // eor'
        for (int i : list) {
   
            if((i & rightOne)==0){
   
                onlyOne = onlyOne ^ i;
            }
        }
        eor_1 = onlyOne ^ eor_1;
        System.out.println(eor_1);
        System.out.println(onlyOne);
    }

1.2 插入排序 O( n 2 n^2 n2

从0-0开始看,到0-1,直到0-n
做到0-0范围上有序,然后0-1范围上有序,一直到0-N范围上有序
从后往前看,若前一个比后一个大则交换,若前面没有数或者相等小于则停止。

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

1.3 二分法O( l o g 2 N log_2 N log2N

  1. 在一个有序数组中,找某个数是否存在?
  2. 在一个有序数组中,找>=某个数最左侧的位置
  3. 局部最小值问题
    先单独判断0位置是不是局部最小。再看n-1位置是不是局部最小。若没有局部最小,则中间必有局部最小。然后二分到中间m为,判断m-1,m,m+1是否有局部最小。
    在这里插入图片描述

1.4 对数器

对数器的概念和使用
1,有一个你想要测的方法a
2,实现复杂度不好但是容易实现的方法b
3,实现一个随机样本产生器
4,把方法a和方法b跑相同的随机样本,看看得到的结果是否一样。
5,如果有一个随机样本使得比对结果不一致,打印样本进行人工干预,改对方法a或者
方法b
6,当样本数量很多时比对测试依然正确,可以确定方法a已经正确。

1.5 递归 O ( N ) O(N) O(N)

求数组中的最大值,用递归的方法
master公式为
T ( N ) = 2 ∗ T ( N / 2 ) + O ( 1 ) T(N) = 2* T(N/2) + O(1) T(N)=2T(N/2)+O(1)
时间复杂度为 O ( N l o g b a ) = O ( N ) O(N^{log_ba})=O(N) O(Nlogba)=O(N)
在这里插入图片描述
master公式
要求每一次子过程规模都是等量的
T ( N ) = a ∗ T ( N / b ) + O ( N d ) T(N) = a* T(N/b) + O(N^d) T(N)=aT(N/b)+O(Nd)
母问题共有N个数据
$T(N/b) 每 一 次 子 过 程 规 模 是 等 量 的 , 都 是 每一次子过程规模是等量的,都是 N/b$的规模, 调用了a次.
除去调用之外的时间复杂度是O(N^d)

l o g b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值