leetcode 零基础小白如何刷题

1

cpp 复制代码
string nextStr(const string& ssp, const string& s){}
//const可以保证函数不会修改ssp的值,&避免向量的拷贝。

Q1:函数的参数为什么不是 vector <string> strs?

  1. 避免不必要的拷贝
    vector<string> 是一个容器,可能包含大量字符串。如果按值传递(vector<string> strs),函数会创建整个容器的副本(包括所有字符串的拷贝),这会消耗额外的时间 (拷贝操作)和内存 (存储副本)。

    而使用引用 & 传递时,函数直接访问原始容器,不会产生任何拷贝,效率更高。

  2. const则保证不会修改ssp

按值传递与按参传递

函数的定义:

cpp 复制代码
类型名 函数名( 形式参数)
{
函数体
}

一些比较烦的题解类型:

范围for循环

(38 封私信 / 26 条消息) C++ 11 新特性:基于范围的 for 循环 - 知乎

基本语法

复制代码
for (declaration : expression) {
    // 循环体
}
  • declaration 是当前范围内元素的声明,通常是一个变量定义,这个变量会依次取得 expression中每个元素的值。
  • expression 是要迭代的序列,可以是花括号括起来的初始化列表、数组、容器类对象等,也可以是返回 string 字符串和容器对象的函数

unordered_map<string, vector<int>> map 中的每个元素都是 std::pair 类型(键值对),其结构是 C++ 标准库预定义的:

cpp

复制代码
// 标准库中 pair 的简化定义
template <class T1, class T2>
struct pair {
    T1 first;  // 键(key)
    T2 second; // 值(value)
};

T1、T2是类型包括结构类型、整型等

范围for循环

for(元素类型 变量名 : 容器){.........}

典中典

cpp 复制代码
unordered_map<string,vector<int>> map;
for(auto& t : map)
{
    vector<string> tempres;
    for(auto& index : t.second)
    {
        tempres.push_back(strs[index]);
    }
    res.push_back(tempres);
}

map 是一个二维向量,或者叫他现在的身份 哈希表!

例子:ate 123

这个t是一个变量哈,他的类型是什么呢,pair!!!

以unordered_map<string,vector<int>> map;为例子

map[原像].push_back(像);当原像不存在时,他会自动创建一个,当存在时,那就在vector<int>中插入像

stl

杂项 | 算竞常用 C++ STL 用法 - 颢天笔记

容器

一、vector(动态数组,最常用的容器)

vector 类似 "可自动扩容的数组",支持随机访问,适合需要频繁添加 / 删除尾部元素的场景。

vector <类型> 容器名(初始的元素数目,元素初值);

vector <int> v;//整数,默认初值为0,指针nullptr

vector <int> v(3);

vector <int> v(3,3);

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

二维vector:

cpp 复制代码
#include <vector>
using namespace std;

// 方式1:直接初始化m行n列,值为0
vector<vector<int>> mat(m, vector<int>(n)); 

// 方式2:初始化m行n列,值为5
vector<vector<int>> mat(m, vector<int>(n, 5)); 

// 方式3:动态构建(先创建空行,再逐行添加)
vector<vector<int>> mat;
for (int i = 0; i < m; i++) {
    vector<int> row;  // 每行可以是不同长度(如邻接表)
    for (int j = 0; j < n; j++) {
        row.push_back(i * j);
    }
    mat.push_back(row);
}

// 方式4:列表初始化(已知元素时)
vector<vector<int>> mat = {{1,2,3}, {4,5,6}, {7,8,9}};

vector<vector<string>> graph(26);

这里先创建一个二十六行的vector,之后graph[i]="adfs",相当于邻接表,在每一行后插入新元素

核心操作

cpp 复制代码
// 访问元素(行索引i,列索引j)
int val = mat[i][j];  // 无越界检查
int val = mat.at(i).at(j);  // 有越界检查(调试用)

// 遍历二维vector(三种方式)
// 方式1:下标遍历
for (int i = 0; i < mat.size(); i++) {
    for (int j = 0; j < mat[i].size(); j++) {
        cout << mat[i][j] << " ";
    }
    cout << endl;
}

// 方式2:迭代器遍历
for (auto it = mat.begin(); it != mat.end(); ++it) {  // it指向一行
    for (auto jt = it->begin(); jt != it->end(); ++jt) {  // jt指向元素
        cout << *jt << " ";
    }
    cout << endl;
}

// 方式3:范围for循环(C++11+)
for (auto& row : mat) {  // row是每行的引用(避免拷贝)
    for (int x : row) {
        cout << x << " ";
    }
    cout << endl;
}

// 清空某一行
mat[0].clear();

// 清空整个二维vector
mat.clear();

场景示例

vector高频操作

  • 邻接表(图的存储):vector<vector<int>> adj(n)adj[u].push_back(v) 表示边 u→v;
  • 动态规划表:vector<vector<int>> dp(m, vector<int>(n, -1)) 存储状态。
操作 语法示例 时间复杂度 场景
排序(升序) sort(v.begin(), v.end()) O(n log n) 需有序序列的场景(二分查找等)
排序(降序) sort(v.begin(), v.end(), greater<int>()) O(n log n) 找前 K 大元素等
自定义排序 sort(v.begin(), v.end(), cmp) O(n log n) 按结构体字段排序等
二分查找(存在性) binary_search(v.begin(), v.end(), x) O(log n) 判断元素是否在有序数组中
二分找第一个≥x lower_bound(v.begin(), v.end(), x) O(log n) 找插入位置、统计≥x 的元素数
二分找第一个>x upper_bound(v.begin(), v.end(), x) O(log n) 统计>x 的元素数、区间划分
去重(需先排序) auto last = unique(v.begin(), v.end()); v.erase(last, v.end()) O(n) 移除相邻重复元素
反转 reverse(v.begin(), v.end()) O(n) 翻转字符串、数组
填充 fill(v.begin(), v.end(), 0) O(n) 初始化数组为特定值
求最大值 *max_element(v.begin(), v.end()) O(n) 找序列最大值
求最小值 *min_element(v.begin(), v.end()) O(n) 找序列最小值
求和(C++17+) accumulate(v.begin(), v.end(), 0) O(n) 计算元素总和(需 #include <numeric>)
cpp 复制代码
vector<int> v = {3, 1, 4, 1, 5, 9};

// 排序(升序)
sort(v.begin(), v.end());  // v变为[1,1,3,4,5,9]

// 去重(需先排序)
auto last = unique(v.begin(), v.end());  // 移动重复元素到尾部,返回第一个重复元素的位置
v.erase(last, v.end());  // v变为[1,3,4,5,9]

// 二分查找第一个≥4的元素
auto it = lower_bound(v.begin(), v.end(), 4);  // 指向4(索引2)
int pos = it - v.begin();  // 转换为下标:2

// 自定义排序(按绝对值从大到小)
vector<int> v2 = {-3, 1, -5, 2};
sort(v2.begin(), v2.end(), [](int a, int b) {
    return abs(a) > abs(b);  // 匿名函数作为比较器
});  // v2变为[-5, -3, 2, 1]
函数 作用 例子(假设 vector<int> v
v.size() 返回元素个数 int n = v.size();(如果有 3 个元素,n=3)
v.empty() 判断是否为空(无元素) if(v.empty()) { ... }
v.push_back(x) 在尾部添加元素 x v.push_back(5);(尾部新增 5)
v.pop_back() 删除尾部元素(无返回值) v.pop_back();(删除最后一个元素)
v.clear() 清空所有元素(容器变为空) v.clear();
v[i] 访问第 i 个元素(下标从 0 开始) int val = v[2];(获取第 3 个元素)
v.resize(n) 调整容器大小为 n(多删少补默认值) v.resize(5);(调整为 5 个元素)
cpp 复制代码
#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 初始化一个vector,包含元素 {1, 2, 3}
    vector<int> v = {1, 2, 3};

    // 1. v.size():返回元素个数
    int n = v.size();
    cout << "初始元素个数:" << n << endl;  // 输出:3


    // 2. v.empty():判断是否为空
    if (v.empty()) {
        cout << "vector为空" << endl;
    } else {
        cout << "vector不为空" << endl;  // 输出:vector不为空
    }


    // 3. v.push_back(x):在尾部添加元素x
    v.push_back(4);  // 尾部添加4,此时v为 {1, 2, 3, 4}
    v.push_back(5);  // 尾部添加5,此时v为 {1, 2, 3, 4, 5}
    cout << "添加元素后,元素个数:" << v.size() << endl;  // 输出:5


    // 4. v[i]:访问第i个元素(下标从0开始)
    int val = v[2];  // 访问下标2的元素(第3个元素)
    cout << "下标2的元素值:" << val << endl;  // 输出:3


    // 5. v.pop_back():删除尾部元素
    v.pop_back();  // 删除尾部的5,此时v为 {1, 2, 3, 4}
    cout << "删除尾部元素后,元素个数:" << v.size() << endl;  // 输出:4
    cout << "当前尾部元素:" << v[v.size() - 1] << endl;  // 输出:4(最后一个元素)


    // 6. v.resize(n):调整大小为n(原元素数<span style="text-decoration: underline;">n时补默认值0,>n时删除多余元素)
    v.resize(5);  // 原大小为4,调整为5,补1个0,此时v为 {1, 2, 3, 4, 0}
    cout << "resize(5)后,元素为:";
    for (int num : v) {
        cout << num << " ";  // 输出:1 2 3 4 0
    }
    cout << endl;


    // 7. v.clear():清空所有元素
    v.clear();
    cout << "clear()后,元素个数:" << v.size() << endl;  // 输出:0
    if (v.empty()) {
        cout << "clear()后,vector为空" << endl;  // 输出:clear()后,vector为空
    }

    return 0;
}

二、queue(队列,先进先出 FIFO)

queue 类似 "排队",只能从队尾添加元素,从队首删除元素,适合 BFS 等场景。

函数 作用 例子(假设 queue<string> q
q.size() 返回队列中元素个数 int n = q.size();
q.empty() 判断队列是否为空 while(!q.empty()) { ... }(非空则循环)
q.push(x) 在队尾添加元素 x q.push("abc");(队尾加入 "abc")
q.pop() 删除队首元素(无返回值,必须先判空) q.pop();(删除最前面的元素)
q.front() 获取队首元素(不删除,必须先判空) string s = q.front();(取最前面的元素)

三、unordered_set(无序集合,元素不重复)

unordered_set 类似 "无重复元素的袋子",查找速度快,适合记录 "已访问""去重" 等场景。

函数 作用 例子(假设 unordered_set<int> s
s.size() 返回元素个数 int n = s.size();
s.empty() 判断是否为空 if(s.empty()) { ... }
s.insert(x) 插入元素 x(若已存在则不插入) s.insert(10);(插入 10)
s.find(x) 查找元素 x,返回迭代器: 找到则指向 x,否则指向 s.end() if(s.find(10) != s.end()) { ... }(判断 10 是否存在)
s.erase(x) 删除元素 x(若存在) s.erase(10);(删除 10)
s.clear() 清空所有元素 s.clear();

四、string(字符串,字符容器)

string 是存储字符的容器,本质是 char 类型的数组封装,支持字符串拼接、比较等操作。

函数 作用 例子(假设 string str = "abc"
str.size() 返回字符个数(长度) int len = str.size();(len=3)
str.empty() 判断字符串是否为空(长度为 0) if(str.empty()) { ... }
str += c 拼接字符 c 或字符串 str += 'd';(str 变为 "abcd")
str.c_str() 转换为 C 风格字符串(const char* cout << str.c_str();(兼容 C 语言函数)
str.substr(i, n) 从下标 i 开始,截取长度为 n 的子串 string sub = str.substr(1, 2);(sub 为 "bc")
str.clear() 清空字符串(变为空串) str.clear();(str 变为 "")
str[i] 访问第 i 个字符(下标从 0 开始)