最值查找

1. min 和 max 函数

minmax是最常用的取值操作。min传出最小值,max传出最大值。注意,正常是只能传入两个数,如果你想传入更多的数,那么你应该考虑使用数组。
下面就是一个使用例子:

max(1, 9)//max(一个数, 另一个数)
min({1, 55, 6543, 23, 9})

时间复杂度为O(1),传入参数为数组时的时间复杂度为O(n),n为数组大小

2. min_element 和 max_element

min_element(st, ed)返回地址[st, ed)最小值的那个地址(迭代器),传入参数为两个地址或迭代器。
max_element(st, ed)返回地址[st, ed)最大值的那个地址(迭代器),传入参数为两个地址或迭代器。

时间复杂度为O(n),n为数组大小(由传入的参数决定)

cout << *max_element(v1.begin(), v1.end()) << endl;

3. nth_element

使用nth_element时,常见的场景是当你不需要对整个序列进行排序,而只需要找到某个特定位置上的元素时。例如,你可以使用nth_element来找到中位数。

vector<int> v ={5, 1, 3, 7, 10, 22, 32};

//输出最大的元素 通过*进行解引用,即通过地址(迭代器)获得值
nth_element(v.begin(), v.begin() + 3, v.end());
//这里v[3]的位置将会位于排序后的位置,其他的任意
for(auto &i : v)cout << i << ' ';

二分查找

1. 二分查找的前提

库函数只能对数组进行二分查找。
对一个数组进行二分查找的前提是这个数组的元素是单调的,一般为单调不减,如果是单调不增的话,就需要改一下比较函数了(跟sort函数用法差不多?)

[1, 3, 3, 5 , 6, 77] //这是单调的
[1, 22, 12, 333, 26] //这不是单调的
[10, 9, 8, 8, 7, 2]  //这是单调的

2. binary_search函数

binary_search函数是c++标准库中的一个算法函数,用于在已排序的序列(例如数组或者容器(一般是vector))中查找特定元素,它通过二分查找算法来确定序列中是否存在目标元素。函数返回一个bool值,并表示目标元素是否存在于序列中。
如果需要获取找到的元素的位置,可以使用std::lower_bound函数或者std::upper_bound函数。

vector<int> n = {1, 3, 5, 7, 9};

int target = 5;

//使用 binary_search 查找目标元素

bool found = binary_search(n.begin(), n.end(), target);

if (found)
{
    cout << "Target element " << target << "found." << "\n";
}
else
{
    cout << "Target element " << target << "not found." << "\n";
}

3. lower_bound 和 upper_bound

前提:数组必须为非降序

如果要在非升序的数组中使用,可以通过修改比较函数实现(方法与sort自定义函数比较类似)。

lower_bound(st, ed, x)//返回地址[st ,ed) 中第一个大于等于x的元素的地址。
upper_bound(st, ed, x)//返回地址[st ,ed) 中第一个大于x的元素的地址。

如果不存在则返回最后一个元素的下一个位置,在vector中即end()。

vector<int> v = {5, 1, 7, 3, 10, 18, 9};
sort(v.begin(), v.end());

for (auto &i : v)cout << i << ' ';
cout << '\n';

//找到数组中第一个大于等于8的元素位置
cout << (lower_bound(v.begin(), v.end(), 8) - v.begin()) << '\n';

大小写转换

1. islower 和 isupper 函数

islower和isuppper是C++标准库中的字符分类函数,用于检查一个字符是否为小写字母或者大写字母。
islower和isupper函数需要包含头文件<cctype>,也可以使用万能头文件。
注意,函数返回值是bool类型

char ch1 = 'A';
char ch2 = 'b';

//使用 islower 函数判断字符是否为小写字母
if (islower(ch1))
{
    cout << ch1 << " is a lowercase letter." << '\n';
}
else
{
    cout << ch1 << " is not a lowercase letter." << '\n';
}

//使用 isupper 函数判断字符是否为大写字母
if (isupper(ch2))
{
    cout << ch2 << " is a uppercase letter." << '\n';
}
else
{
    cout << ch2 << " is not a uppercase letter." << '\n';
}

2. tolower 和 toupper 函数

tolower(char ch)可以将ch转换为小写字母,如果ch不是大写字母则不能进行操作。
toupper()同理。

char ch1 = 'A';
char ch2 = 'b';

//使用 tolower 函数将字符转换为小写字母
char lowercaseCh1 = tolower(ch1);
cout << "Lowercase of " << ch1 << "is " << lowercaseCh1 << '\n';

//使用 toupper 函数将字符转换为大写字母
char lowercaseCh2 = toupper(ch2);
cour << "Uppercase of " << ch2 << "is " << uppercaseCh2 << '\n';

3. ASCII码

图3.1 ASCII码表

</div class = “center”>

‘c’ – ‘a’ + ‘A’ = ‘C’

在了解ASCII码后,我们可以通过直接对英文字母进行加减运算计算出其大小写的字符。
在ASCII码表中,大写字母的编码范围是65(‘A’)到90(‘Z’),而小写字母的编码范围是97(‘a’)到122(‘z’),根据这个规则,可以使用ASCII码表进行大小写转换。

char ch = 'A';// 大写字母
char convertedCh;

if (ch >= 'A' && ch <= 'Z')
{
    //大写字母转换为小写字母
    convertedCh = ch + 32;
    cout << "Converted character: " << convertedCh << '\n';
}
else if (ch >= 'a' && ch <= 'z')
{
    convertedCh = ch - 32;
    cout << "Converted character: " << convertedCh << '\n';
}
else
{
    cout << "Invaild character!" << '\n';
}

设计程序并使用char类型时,注意一下是数字0-9还是字符0-9

全排列

1. next_permutation()函数

next_permutation函数用于生成当前序列的下一个排列。它按照字典序对序列进行重新排列,如果存在下一个排列,则将当前序列更改为下一个排列,并且返回true;如果当前序列已经是最后一个序列,则将序列更改为第一个序列,并且返回false。

vector<int> nums = {1, 2, 3};

cout << "Initial permutation: ";
for (int num : nums)
{
    cout << num << ' ';
}
cout << '\n';

// 生成下一个排列
while (next_permutation(nums.begin(), nums.end()))
{
    cout << "Next permutation: ";
    for (int num : nums)
    {
        cout << num << ' ';
    }
    cout << '\n';
}

其它库函数

1. memset()

memset() 是一个用于设置内存块值的函数。
它的原型定义在<cstring>头文件中,函数的声明如下:

void* memset(void* ptr, int val, size_t num);
//ptr: 指向要填充的内存块的指针
//val:要设置的值,该值以int的形式提供,但函数填充该值的无符号字符转换形式
//num:要被设置为该值的字节数

//memset()函数将ptr指向的内存块的前num个字节设置为value的值。它返回一个指向ptr的指针(返回值一般我们用不上) 
  • 解释:复制字符 c(一个无符号字符)到参数 str 所指向的字符串的前 n 个字符。
  • 作用:是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
  • 头文件:C中#include <string.h>,C++中#include <cstring>
int arr[10];
memset(arr, 0, sizeof(arr));

上述示例当中,memset(arr, 0, sizeof(arr))将数组arr的所有元素设置为0。
需要注意的是,memset()函数对于非字符类型的数组可能会产生未定义行为。
在处理非字符类型的数组时,更好使用C++中的其它方法,如循环遍历来初始化数组。

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int a[5];
    memset(a, 1, sizeof(a));
    for (int i = 0; i < 5; ++ i)cout << bitset<32>(a[i]) << '\n';
    return 0;
}

2. swap()

swap(T &a,T &b)函数需要接收两个参数
a:要交换值的第一个变量的引用
b:要交换值的第二个变量的引用
swap()函数通过将第一个变量的值存储到临时变量中,然后将第二个变量的值赋给第一个变量,最后将临时变量的值赋给第二个变量,实现两个变量值的交换。
swap()函数可以用于交换任意类型的变量,包括基本类型(如整数、浮点数等)和自定义类型(如结构体、类对象等)。

int a = 20;
int b = 10;
std::swap(a, b);

3. reverse()

reverse()是一个用于反转容器中元素顺序的函数。
它的原型定义在<algorithm>头文件中。

比如翻转一个字符串str

string str = "hello world";
reverse(str.begin(), str.end());

拓展知识

1. 迭代器

迭代器类似于指针,提供了对象的间接访问,但获取迭代器并不是使用取地址符。如果将指针理解为元素的“地址”,那么迭代器可以理解为元素的“位置”。可以使用迭代器访问某个元素,迭代器也能从一个元素移动到另一个元素。

一个迭代器的范围由一对迭代器表示,分别为 begin 和 end。其中 begin 成员返回指向第一个元素的迭代器;end 成员返回容器最后一个元素的下一个位置(one past the end),也就是指向一个根本不存在的尾后位置,这样的迭代器没什么实际含义,仅是个标记而已,表示已经处理完了容器中的所有元素。所以 begin 和 end 表示的是一个左闭右开的区间[begin, end)

迭代器可以用来实现容器的遍历、插入等操作。

2. 指针(*)、取地址(&)、解引用(*)、引用(&)

在C语言中,创建变量就是在向内存申请空间。

#include <iostream>

int main()
{
    int a = 10;
}

2.1 指针

3. 0x3f ~ 0x3f3f3f3f

在计算机解决问题时,时常要将一些变量初始化为极大值,比如说无穷大\infty
众所周知,计算机的存储空间是有限的,使用0x3f3f3f3f作为极大值来表示\infty

int m = 0x3f3f3f3f;
cout << m << '\n';

4. 原码、反码、补码

4.1 原码

正常的二进制表达,需要注意的是,最左的位是符号位,0为正1为负