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<int> selectSort(vector<int> 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<int> bubbleSort(vector<int> 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 异或运算的性质与扩展
- 0^N == N N^N == 0
- 异或运算满足交换律和结合率
- 不用额外变量交换两个数
// 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到这一个数
int appearOnce(vector<int> arr)
{
int eor = 0;
for (int &cur : arr)
{
eor ^= cur;
}
return eor;
}
// 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到这两个数
vector<int> appearTwice(vector<int> arr)
{
vector<int> 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<int> insertSorted(vector<int> 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 二分法的详解与拓展
- 在一个有序数组中,找某个数是否存在
- 在一个有序数组中,找>=某个数最左侧的位置
- 局部最小值问题(无序数组)
int localMinimum(vector<int> 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公式
→ 复杂度为
→ 复杂度为
→ 复杂度为