最近的三数之和 16
排序➕双指针(优化一层循环)
class Solution {
public:
int threeSumClosest(vector
sort(nums.begin(),nums.end());
//双指针优化一重循环
int ans = nums[0] + nums[1] + nums[2];
for(int i=0;i
while(j
if(abs(target - sum) < abs(target - ans))
ans = sum;
if(sum > target) k--;
else if(sum < target) j++;
else return ans;
}
}
return ans;
}
};
喧闹和富有 DAG
bfs 拓扑排序
class Solution {
int n, G[501][501] = {0}, in[501] = {0};
vector
public:
vector
{
n = quiet.size();
ans.resize(n);
for(auto &r : richer)
G[r[0]][r[1]] = 1, ++in[r[1]];//钱多 → 钱少
queue
for(int i = 0; i < n; ++i) ans[i] = i;
for(int i = 0; i < n; ++i) if(!in[i]) q.push(i);
while(!q.empty()){
int u = q.front(); q.pop();
for(int v = 0; v < n; ++v) if(G[u][v]){
if(quiet[ans[u]] < quiet[ans[v]]) ans[v] = ans[u];
if(!--in[v]) q.push(v);
}
}
return ans;
}
};
dfs记忆化搜索
class Solution {//DFS 记忆化
int n, G[501][501] = {0};
vector
void dfs(int u, vector
{
if(ans[u] != -1) return; //memo
ans[u] = u;
for(int v = 0; v < n; ++v)
if(G[u][v])
{//如果存在比 u 更有钱的人 v
dfs(v, quiet);
if(quiet[ans[v]] < quiet[ans[u]])
ans[u] = ans[v];
}
}
public:
vector
n = quiet.size();
ans.resize(n, -1);
for(auto &r : richer) G[r[1]][r[0]] = 1;
//钱少 → 钱多
for(int i = 0; i < n; ++i) dfs(i, quiet);
return ans;
}
};
克隆图 lc113
hash+dfs
class Solution {
public:
unordered_map
Node* cloneGraph(Node* node) {
if(!node) return NULL;
return dfs(node);
}
Node* dfs(Node* node)
{
//node节点已经被访问过了,直接从哈希表hash中取出对应的克隆节点返回。
if(hash[node]) return hash[node];
Node* clone = new Node(node->val); //克隆节点
hash[node] = clone; //建立源节点到克隆节点的映射
for(Node* ver: node->neighbors) //克隆边
{
clone->neighbors.push_back(dfs(ver));
}
return clone;
}
};
出入度 997
class Solution {
public:
int findJudge(int n, vector
vector
vector
for (auto& t : trust) {
int a = t[0], b = t[1];
outDegree[a]++; // a信任b,a的出度+1
inDegree[b]++; // b被a信任,b的入度+1
}
// 遍历寻找法官:入度n-1且出度0
for (int i = 1; i <= n; i++) {
if (inDegree[i] == n - 1 && outDegree[i] == 0) {
return i;
}
}
return -1;
}
};
cpp function函数包装器
C++函数包装器就像是一个“万能盒子”,能把各种可调用的东西(比如普通函数、类的成员函数、Lambda表达式)统一装起来,然后像调用普通函数一样用。
好处:
简单说,它让函数使用更灵活,就像用一个通用遥控器控制不同电器。
图路径 1971
tip 两个true的场景
class Solution {
public:
bool validPath(int n, vector
{
vector
for(auto& a:edges)
{
grip[a[0]].push_back(a[1]);
grip[a[1]].push_back(a[0]);
}
vector
//防止死循环
function
[&](int i)->bool
{
if(i==destination)
return true;
vis[i]=true;
for(auto& j:grip[i])
{
if(!vis[j] && dfs(j))
return true;
}
return false;
};
return dfs(source);
}
};
并查集
class Solution {
public:
bool validPath(int n, vector
vector
iota(p.begin(), p.end(), 0);
function
if (p[x] != x) p[x] = find(p[x]);
return p[x];
};
for (auto& e : edges) p[find(e[0])] = find(e[1]); //构建并查集 下标里存的是终点
return find(source) == find(destination);
}
};
“并查集”判断两点是否连通,像在处理“朋友关系网”问题:
核心逻辑:
1. 初始化关系网:
- vector
2. 找老大函数(find):
- 递归找某个点的最终老大,同时“路径压缩”(让沿途点直接认老大,提高后续查找效率)。比如点A的老大是B,B的老大是C,就直接让A认C当老大。
3. 合并关系:
- 遍历所有边 edges ,把边两端的点所属集合合并(让它们的老大认同一个老大)。比如边连了点1和点2,就把1和2的老大合并成一伙。
4. 判断连通性:
- 最后看起点和终点的老大是否相同,相同则连通(在一个朋友圈里)。
通俗类比:
- n个点是n个人,edges是“朋友关系”,source和destination是要判断的两个人。
- 并查集就像给每个人找“社团老大”,朋友的朋友算同一社团。最后看两人是否同社团,同社团就有路径连通。
atoi iota
atoi
作用:把字符串“翻译”成整数。
比如 "123" 用 atoi 处理后就是数字 123 ,遇到非数字字符会停止转换(如 "12a3" 转成 12 )。
iota
作用:给数组或容器“批量填数”,从某个值开始依次递增。
比如用 iota(arr, arr+3, 5) ,会让数组前3个元素变成 5,6,7 ,像自动按顺序贴标签。
总结:atoi 是“字符串→数字”转换器,iota 是“批量填递增数”的工具。
极大极小值 2239
模拟->原地模拟
class Solution {
public:
int minMaxGame(vector
for (int n = nums.size(); n != 1; n /= 2) {
vector
for (int i = 0; i < n / 2; i++)
tem[i] = i % 2? max(nums[2 * i], nums[2 * i + 1]) : min(nums[2 * i], nums[2 * i + 1]);
nums = tem;
}
return nums[0];
}
};
原地模拟
class Solution {
public:
int minMaxGame(vector
for (int n = nums.size(); n != 1; n /= 2)
{
for (int i = 0; i < n / 2; i++)
nums[i] = i % 2? max(nums[2 * i], nums[2 * i + 1]) : min(nums[2 * i], nums[2 * i + 1]);
}
return nums[0];
}
};
递归模拟
class Solution {
public:
int minMaxGame(vector
return fun(nums, nums.size());
}
int fun(vector
if (n == 1) return nums[0];
for (int i = 0; i < n / 2; i++) nums[i] = i % 2? max(nums[2 * i], nums[2 * i + 1]) : min(nums[2 * i], nums[2 * i + 1]);
return fun(nums, n / 2);
}
};
图论简单bfs lcp07
class Solution {
public:
int numWays(int n, vector
vector
for (auto& a : relation)
grip[a[0]].push_back(a[1]);
queue
int ret = 0;
if (k > 0) { // 当k=0时无需移动
for (auto& g : grip[0])
q.push(g);
}
while (k > 0 && !q.empty()) {
int sz = q.size();
k--;
while (sz--) {
auto x = q.front();
q.pop();
if (k==0 && x == n - 1) ret++;
for (auto& next : grip[x])
q.push(next);
}
}
return ret;
}
};