重拾C++(算法版)

前言

笔者两年前用的C++,后来发现python这种神器,用的python较多,且用于刷leetcode,现在因为工作原因重新拿起了C++,话说两年前立志要把那本C++primer看完的决心又可以启程了,废话不多说,以下是刷leetcode时,用到C++的一些库函数,也是基础,是自己的笔记,但也是刷题必备呀有木有,简直如虎添翼,不然跟C有啥区别的。

一、数据结构

1. vector—基础结构

1.1 初始化

#include <vector>
std::vector<int> newList;
std::vector<int> newList={1,2,3};
std::vector<int> newList(1,2;

二维数组

vector<vector<int>> newVec(rowNum, vector<int>(columnsNum, 0))

https://blog.csdn.net/yjunyu/article/details/77728410

//在b开始位置处插入6个6
b.insert(b.begin(), 6, 6);

1.2 预设空间

std::vector<int>test3;
test3.reserve(2); # 预设两个位置
test3.resize(2,1); # 在test3的前两个位置赋值-21,如果有值则不赋

1.3 erase用法

https://blog.csdn.net/u013654125/article/details/77321081
vector<int> iVec;
for (auto it = iVec.begin(); it != iVec.end();) {
	 if (*it % 3 == 0)
     	it = iVec.erase(it); //删除元素,返回值指向已删除元素的下一个位置 
     else
     	++it; //指向下一个位置
}

1.4 求最大值

https://blog.csdn.net/qxconverse/article/details/67638545
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(){
    vector<int> a = { 2,4,6,7,1,0,8,9,6,3,2 };
    auto maxPosition = max_element(a.begin(), a.end());
    cout << *maxPosition << " at the postion of " << maxPosition - a.begin() <<endl;
    //cout << a[maxPosition - a.begin()] << " at the postion of " << distance(a.begin(), maxPosition) << endl;
    system("pause");
    return 0;
}

1.5 求和

int sumOfTheVector=accumulate(thisIsVector.begin(),thisIsVector.end(),0); 

1.6 insert(list也可)

  1. 可以直接插入目标位置,其他的元素后移;
  2. 这个目标位置指定为迭代器形式,可以用advance进行后移操作;
	vector<int> vec;
    vec.push_back(4);
    vec.push_back(6);
    auto pos = vec.begin();
    advance(pos, 1);
    vec.insert(pos, 7); // 也可以是 vec.insert(vec.begin() + 1, 7)
    for (auto i : vec) {
        cout << i << endl;
    }

注意:位置的迭代器的初始要跟插入的vector一致。

1.6.1 把一个vector里的元素追加放入另外一个vector
std::vector<int> src;
std::vector<int> dest;
dest.insert(dest.end(), src.begin(), src.end());

1.7 原地“删掉”重复值

vector<int> vec1 = {0, 2, 1, 1};
sort(vec1.begin(), vec1.end());
auto end_unique = unique(vec1.begin(), vec1.end());

注:这里“删掉”打引号,因为这不是真正的删除,而是把vec1中的重复的值放在vector的最后面(位置未知),vec1即为操作后的vector,而返回值即为最后一个不重复元素之后的位置。

1.8 push_back 和 pop_back

2. unordered_set/set—迅速找到某个值

https://blog.csdn.net/zhang14916/article/details/100859487

类似与python的set集合,有find的方法,另外有个特性就是里面的元素没有重复的。

2.1 初始化

#include <unordered_set>
std::unordered_set<std::string> c{"aaa"};

2.2 find(count-查找个数)

a.find(“eeee”):查找元素"eeee",返回结果为a.end()则表明没有找到,否则返回所对应元素。

2.3 遍历取数

  • 注:set结构的遍历出来的数每次都可能不同,这是因为set存放是无序且不同的数。
  • 方法一
    unordered_set<int> set;
    for (int i = 0; i < 10; i++) {
        set.insert(set[i]);
    }
    for (unordered_set<int>::iterator i = set.begin(); i != set.end(); i++) {
        cout << *i << endl;
    }
    cout << " find 3: " << *set.find(3) << endl;
    cout << "count 5:" << set.count(5) << endl;
  • 方法二(推荐)
    unordered_set<int> set;
    for (int i = 0; i < 10; i++) {
        set.insert(set[i]);
    }
    for (auto &s : set) {
        cout << s << endl;
    }

2.4 存储数对

pair<int, int> # 声明的时候
make_pair(0, 0) # 构造pair数对
auto result = make_pair(0, 0) # 数对构造后存入auto类型的变量中
  • set和pair数对的结合使用 —— 实例
bool Solution::isPathCrossing(string path) {
  set<pair<int, int>> temp;
  temp.insert(make_pair(0, 0));
  int x = 0;
  int y = 0;
  for (auto &d : path) {
    switch (d) {
      case 'N':
        y += 1;
        break;
      case 'E':
        x += 1;
        break;
      case 'S':
        y -= 1;
        break;
      case 'W':
        x -= 1;
        break;
    }
    auto newLocation = make_pair(x, y);
    if (temp.count(newLocation)) {
      return true;
    }
    temp.insert(newLocation);
  }
  return false;
}

2.5 vector直接转set

vector<string> wordList;
unordered_set<string> dict(wordList.begin(), wordList.end());

3. unordered_map/map—字典

https://blog.csdn.net/u012604810/article/details/79798082
https://leetcode-cn.com/problems/subarray-sums-divisible-by-k/solution/he-ke-bei-k-zheng-chu-de-zi-shu-zu-by-leetcode-sol

3.1 初始化

#include <unordered_map>
unordered_map<int, int> record = {{0, 1}};
  • 注:结构里没有的key的值都为0

3.2 find函数

iterator find ( const key_type& key );

如果key存在,则find返回key对应的迭代器,如果key不存在,则find返回unordered_map::end。因此可以通过

map.find(key) == map.end()来判断,key是否存在于当前的unordered_map中。

⚠️注意:如果key为结构体,要查找的话,必须要key变为指针。

3.3 Count函数

size_type count ( const key_type& key ) const

count函数用以统计key值在unordered_map中出现的次数。实际上,c++ unordered_map不允许有重复的key。因此,如果key存在,则count返回1,如果不存在,则count返回0.

3.4 insert函数

unordered_map<int, int> map1;
map1.insert({1, 3});

3.5 取数

int res = map1[1];
auto temp = map1.find(1);
int res = temp.second;

3.6 map是能排序的, 默认是less

https://blog.csdn.net/liqinzhe11/article/details/79278235

  • 对map的key进行排序

定义成这样即可:

map<int, int, greater<int>> mp1; // 降序
map<int, int, less<int>> mp2; // 升序

3.7 erase操作

int oldPrice = timePriceMap[timestamp];
priceCntMap[oldPrice]--;
if (priceCntMap[oldPrice] == 0) {
    priceCntMap.erase(oldPrice);
}

3.8 map中----lower_bound和upper_bound的用法

https://blog.csdn.net/qian2213762498/article/details/79250097

4. string—字符串

https://blog.csdn.net/wallwind/article/details/6827863

4.1 初始化

#include <string>
string s(1, '2');

4.2 find

s.find(‘a’) 字符串 s查询’a’字符或字符串 返回所在的位置
s.find(‘a’, n) 字符串s从n下标开始查询’a’字符或字符串 返回所在的位置
如果找不到返回 string::npos(-1)

4.3 切片操作(python说法)

String.substr(first_idx, nums) # 从first_idx索引开始nums个字符

4.4 字符串、数字互转

std::cout<<std::to_string(3)<<"\n";
std::cout<<std::stoi("123")<<"\n";

同时有:stol(long), stof(float), stod(double)

4.5 一句话逆序

  • 方法一
std::cout<<"======string====="<<"\n";
std::string str("asgdasfd");
std::string s(str.rbegin(),str.rend());
std::cout<<s<<"\n";
  • 方法二(原地算法)
std::string str("asgdasfd");
reverse(str.rbegin(),str.rend());
std::cout << str << "\n";

4.6 分割字符串

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
void split(const string& s,vector<int>& sv,const char flag = ' ') {
    sv.clear();
    stringstream iss(s);
    string curr;

    while (getline(iss, curr, flag)) {
    	if(curr.size() > 0){
        	sv.push_back(stoi(curr));
        }
    }
    return;
}

int main() {
    string s("123:456:7");
    vector<int> sv;
    split(s, sv, ':');
    for (const auto& s : sv) {
        cout << s << endl;
    }
    system("pause");
    return 0;
}

5. stack/queue—栈和队列

5.1 用法

#include <stack>
#include <queue>

std::cout << "====stack=====" << "\n";
std::stack<int> test;
test.push(2);
test.push(5);
test.push(4);
int sdfdf = test.top();
std::cout << test.top() << "\n";

std::cout << "====queue=====" << "\n";
std::queue<int> t;
t.push(1);
std::cout << t.front() << "\n";
std::cout << t.back() << "\n";

注:均不可遍历、不可赋值初始化

6. deque—双向队列(力荐)

个人感觉比较无敌,可以赋值初始化,遍历,两边可进,可出。

std::cout << "========deque==========" << "\n";
std::deque<int> testD(6,3);
for (int i = 0; i < testD.size(); i++){
	std::cout << testD[i] << " ";
}

(栗子待补)

7. priority_queue(优先队列)

https://blog.csdn.net/weixin_36888577/article/details/79937886

7.1 使用场景

算法题中,当要频繁求一个数据结构中的最大值时,要想到用优先队列。

7.2 常用函数

top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace 原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容

7.3 leetcode例题

  1. 移除石子使总数最小

二、应用笔记

1. 排序

1.1 一般排序

https://blog.csdn.net/w_linux/article/details/76222112
#include <iostream>
#include <algorithm>
boolmyfunction2(int i, int j)
{ return (i > j); }//降序排列
int main(){
	int a[20] = {2, 4, 1, 23, 5, 76, 0, 43, 24, 65}, i;
    for (i = 0; i < 20; i++)
        cout << a[i] << endl;
    sort(a, a + 20);
    for (i = 0; i < 20; i++)
        cout << a[i] << endl;
    std::vector<int> a = {2, 4, 1, 23, 5, 76, 0, 43, 24, 65};
    int i;
    for (i = 0; i < 10; i++)
        std::cout << a[i] << std::endl;
    # std::sort(a.begin(), a.end()); 默认两个参数升序排序
    std::sort(a.begin(), a.end(), myfunction2);
    for (i = 0; i < 10; i++)
        std::cout << a[i] << std::endl;
    return 0;
}	
vector<int> vector1 = {1,2,3,4,5,6};
sort(vector1.begin(), vector1.end(), greater<int>());// 降序
sort(vector1.begin(), vector1.end(), less<int>());// 升序
sort(people.begin(), people.end(), [=](const vector<int> &p1, const vector<int> &p2) {
return p1[0] > p2[0] || (p1[0] == p2[0] && p1[1] < p2[1]);
});
  • 注意:
    1. 如果vector里面是string类型,则直接sort是可以字符串排序的;
    2. vector里面也可以是其他的自定义数据类型,自定义数据类型加相应的比较大小的函数即可;

1.2 排序返回下标

vector<int> vT = {1,2,8,3};
vector<int> vecIdx(vT.begin(), vT.end());
std::iota(vecIdx.begin(), vecIdx.end(), 0);
sort(vecIdx.begin(), vecIdx.end(), [&vT](const int &index1, const int &index2) {
    return vT[index1] > vT[index2];
});
for (auto i : vecIdx) {
    cout << i << " ";
}
// 2 3 1 0 

2. 正无穷和负无穷

求数组的max和min的时候都需要假设初始值为正无穷或者负无穷,当然也可以随意从数组中取一个值作为初始值,通常取第一个。
在c++中怎么表示正无穷和负无穷呢?

如果是int,可以用INT_MAX表示正无穷,INT_MIN表示负无穷,需要包含limits.h。
如果是double,可以用DBL_MAX表示正无穷,-DBL_MAX表示负无穷(注意不是DBL_MIN),需要包含float.h。

http://blog.csdn.net/caroline_wendy/article/details/24311895

头文件: #include

在这里插入图片描述

3. 求两值最大最小值

3.1 表达式

std::max(a, b)
std::min(a, b)

3.2 注意

只能比较两个元素

4 幂运算

需要注意:

对于C++,幂运算最好预先算出,避免超过数据类型预设的容量。

如:

vector<long long> pow1(nums.size() + 2);
pow1[0] = 1;
for (int i = 1; i < nums.size(); i++) {
    pow1[i] = pow1[i - 1] * 2 % mod;
}

5 长整型

#typedef long long ll;
using ll = long long;
const ll maxValue = 1e9 + 7;

6 二叉树

结点的复制是引用,对复制后的那个结点操作也是对复制前的结点操作。

7 STL查找总结

set<int> set2 = {1,2};
auto f = set2.find(1);
if (f != set2.end()) {
    cout << "f ok " << endl;
}
set2.erase(f);
for (auto item : set2) {
    cout << item << endl;
}

string hello = "asdfgdg";
auto f5 = hello.find('h');
if (f5 == -1) {
    cout << "yes" << endl;
}

vector<int> vec1 = {1,2,3,4,5};
auto fi = find(vec1.begin(), vec1.end(), 1);
if (fi != vec1.end()) {
    cout << "find  1" << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thomas_Cai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值