E1 认识复杂度和简单排序算法

1. 时间复杂度

1.1 常数时间的操作

一个操作如果和样本的数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作。

时间复杂度为一个算法流程中,常数操作数量的一个指标。常用O(读作big O)来表示。具体来说,先要对一个算法流程非常熟悉,然后去写出这个算法流程中,发生了多少常数操作, 进而总结出常数操作数量的表达式。

在表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如果为f(N),那 么时间复杂度为O(f(N))。

1.2 选择排序、冒泡排序细节的讲解与复杂度分析

1.2.1 选择排序

时间复杂度是,空间复杂度是

思路:从0位置开始排序,选择0到n-1位置上最小的数字放到0位置,再找1到n-1位置的最小值放到1位置,反复操作,直到n-1位置

vector selectSort(vector arr)
    {
        int length = arr.size();
        if (length <= 1)
            return arr;
        for (int i = 0; i <= length - 2; i++)
        {
            int minIndex = i;
            for (int j = i + 1; j <= length - 1; j++)
            {
                minIndex = arr[j] < arr[minIndex] ? j : minIndex;
            }
            swap(arr[i], arr[minIndex]);
        }
        return arr;
    }

1.2.2 冒泡排序

时间复杂度是,空间复杂度是

思路:从0位置开始,同后一个数进行比较,大的数向后移动,最终使得最大的数排在了最后一个,反复进行操作,知道标志位为0。

vector bubbleSort(vector arr)
    {
        int length = arr.size();
        if (length <= 1)
            return arr;
        for (int i = length - 1; i > 0; i--)
        {
            for (int j = 0; j < i; j++)
            {
                if (arr[j] > arr[j+1])
                {
                    swap(arr[j+1], arr[j]);
                }
            }
        }
        return arr;
    }

1.3 异或运算的性质与扩展

  1. 0^N == N N^N == 0
  2. 异或运算满足交换律和结合率
  3. 不用额外变量交换两个数
// 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到这一个数
int appearOnce(vector arr)
    {
        int eor = 0;
        for (int &cur : arr)
        {
            eor ^= cur;
        }
        return eor;
    }
// 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到这两个数
vector appearTwice(vector arr)
    {
        vector ans;
        int eor = 0;
        for (int cur : arr)
        {
            eor ^= cur;
        }
        // 此时eor == a^b

        // 原码&补码,可以获得最右边的一个为1的位置
        int righthand = eor & (~eor + 1);
        int eor2 = 0;
        for (int cur : arr)
        {
            if ((righthand & cur) != 0)
            {
                eor2 ^= cur;
            }
        }
        ans.push_back(eor2);
        ans.push_back(eor ^ eor2);
        return ans;
    }

1.4 插入排序细节的讲解与复杂度分析

时间复杂度是,空间复杂度是

算法流程按照最差情况来估计时间复杂度

思路:将当前第个位置上的数同前一个数进行大小比较,如果更小则向前移动,移动之后再同前一个数进行比较,直到比起一个数更大,此时即保证了在到位置有序,移动到下一个位置,直到数组末尾

vector insertSorted(vector arr)
    {
        int length = arr.size();
        for (int i = 0; i < length; i++)
        {
            for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--)
            {
                swap(arr[j + 1], arr[j]);
            }
        }
        return arr;
    }

1.5 二分法的详解与拓展

  1. 在一个有序数组中,找某个数是否存在
  2. 在一个有序数组中,找>=某个数最左侧的位置
  3. 局部最小值问题(无序数组
int localMinimum(vector arr)
    {
        int left = 0;
        int right = arr.size() - 1;

        while (1)
        {
            if (arr[left] < arr[left + 1])
            {
                return left;
            }
            if (arr[right] < arr[right - 1])
            {
                return right;
            }
            int middle = (left + right) >> 1;
            if (arr[middle] < arr[middle + 1] && arr[middle] < arr[middle - 1])
            {
                return middle;
            }
            else
            {
                if (arr[middle] >= arr[middle - 1])
                {
                    right = middle - 1;
                }
                else
                {
                    if (arr[middle] >= arr[middle + 1])
                    {
                        left = middle + 1;
                    }
                }
            }
        }
        return 0;
    }

1.7 时间复杂度估算

  • master公式

→ 复杂度为

→ 复杂度为

→ 复杂度为

你可能感兴趣的:(E1 认识复杂度和简单排序算法)