最常见的优化:
1 记忆化搜索: 使用hash记录遍历起点对应的值,然后直接从hash中获得,避免重复计算
2 常见算法:
对于欧拉图和半欧拉图算欧拉路径:
hierholzer算法参考:
圈:任选图中一个顶点为起点,沿着不重复的边,经过不重复的顶点为途径,之后又回到起点的闭合途径称为圈。
欧拉路径:通过图中所有边一次且仅一次遍历所有顶点的路径称为欧拉(Euler)路径;
欧拉回路:通过图中所有边一次且仅一次行遍所有顶点的回路称为欧拉回路;
欧拉图:具有欧拉回路的图称为欧拉图;
半欧拉图:有欧拉路径但没有欧拉回路的图称为半欧拉图。
欧拉图与半欧拉图的判定:
G是欧拉图 ⇔ G中所有顶点的度均为偶数 ⇔ G是若干个边不重的圈的并。
G是半欧拉图 ⇔ G中恰有两个奇数度顶点。
class Solution {
public:
int edgeNums = -1;
int nodeNums = -1;
unordered_map<string, int> nodes;
unordered_map<int, string> toStr;
vector<string> findItinerary(vector<vector<string>>& tickets) {
// map str to int according to dictionary order
set<string, std::less<string>> airports;
for(auto& vec : tickets) {
airports.insert(vec[0]);
airports.insert(vec[1]);
}
int i = 0;
for(auto& str : airports) {
toStr[i] = str;
nodes[str] = i++;
}
// construct the adj table
int nodeNums = airports.size();
int edgeNums = tickets.size();
// vector<vector<int>> table(nodeNums, vector<int>(0));
vector<priority_queue<int, vector<int>, greater<int>>> table(nodeNums, priority_queue<int, vector<int>, greater<int>>());
for(auto& vec : tickets) {
table[nodes[vec[0]]].push(nodes[vec[1]]);
}
vector<string> strRes;
vector<priority_queue<int, vector<int>, greater<int>>> tableTmp(table);
vector<int> res;
dfs(nodes["JFK"], tableTmp, res);
reverse(res.begin(), res.end());
for(auto& node : res) {
strRes.push_back(toStr[node]);
}
return strRes;
}
//
void dfs(int st, vector<priority_queue<int, vector<int>, greater<int>>>& map, vector<int>& res) {
while(!map[st].empty()) {
int nextSt = map[st].top();
map[st].pop();
// cout << "from to: " << toStr[st] << " -> " << toStr[nextSt] << endl;
dfs(nextSt, map, res);
}
res.emplace_back(st);
}
};
class Solution {
public:
int n = -1;
int k = -1;
vector<char> kVec;
string crackSafe(int n, int k) {
// since for each bit, there a k's possiblity
// so the final str's length = k^n
// consider a G, vertices are {0, 1, ..., k-1}
// for each edge: vi -> vj(vi could equal vj),
// there shall be n-1's such same edge
// we just need a way to walk through the G
// try hierholzer algo
if(1 == n) {
string tmpRes = "";
for(int i = 0; i < k; ++i) {
tmpRes.push_back(i + '0');
}
return tmpRes;
}
this->k = k;
this->n = n;
for(int i = 0; i < k; ++i) {
kVec.push_back(i + '0');
}
unordered_set<string> seen;
unordered_map<string, vector<char>> graph;
buildGraph("", n - 1, graph);
string stStr(n-1, '0');
string res = "";
hierholzer(stStr, graph, res, seen);
// when n=3, k=3, we start from "00" node, so we add reverse of "00" to the end of the res, cause hierholzer produce a reverse eular path (start from "00", end to "00")
res += stStr;
return res;
}
void buildGraph(string tmp, int leftBitNum, unordered_map<string, vector<char>>& graph) {
if(0 == leftBitNum) {
// cout << "len: " << leftBitNum << "finish node: " << tmp << endl;
graph[tmp] = kVec;
return;
}
for(int st = 0; st < k; ++st) {
buildGraph(tmp + kVec[st], leftBitNum-1, graph);
}
}
void hierholzer(
string st,
unordered_map<string, vector<char>>& graph,
string& res,
unordered_set<string>& seen) {
// cout << "doing : " << st << endl;
bool hasOut = false;
for(int edIdx = 0; edIdx < k; ++edIdx) {
string curEdge(st);
curEdge.push_back(graph[st][edIdx]);
if(seen.count(curEdge)) {
continue;
}
hasOut = true;
string nextSt = curEdge.substr(1);
// cout << "st -> nextSt: " << st << " -> " << nextSt << endl;
seen.insert(curEdge);
// cout << "see edge: " << curEdge << endl;
hierholzer(nextSt, graph, res, seen); // post order
res.push_back(graph[st][edIdx]); // hierholzer
}
}
};
class Solution {
public:
int ringLen = -1;
int keyLen = -1;
int findRotateSteps(string ring, string key) {
unordered_map<char, vector<int>> ringMap;
ringLen = ring.length();
keyLen = key.length();
int pos = 0;
for(auto& c : ring) {
if(0 == ringMap.count(c)) {
vector<int> tmp = {pos};
ringMap[c] = tmp;
} else {
ringMap[c].push_back(pos);
}
++pos;
}
vector<vector<int>> memo(keyLen, vector<int>(ringLen, INT_MAX));
return dfsMemo(0, 0, ringMap, key, memo);
}
// no memo dfs, too slow
int dfs(int tar, int markPos, unordered_map<char, vector<int>>& ringMap, string& key) {
if(tar == key.length()) {
return 0;
}
int minStep = INT_MAX;
// for cur key char, try ervery possible way on the ring
for(auto tarPos : ringMap[key[tar]]) {
int curStep = minDis(tarPos, markPos); // rotate
curStep += 1; // write
minStep = min(
minStep,
dfs(tar + 1, tarPos, ringMap, key) + curStep
);
}
return minStep;
}
// memo version
int dfsMemo(int tar, int markPos, unordered_map<char, vector<int>>& ringMap, string& key,
vector<vector<int>>& memo) {
if(tar == key.length()) {
return 0;
}
if(INT_MAX != memo[tar][markPos]) {
return memo[tar][markPos];
}
// for cur key char, try ervery possible way on the ring
for(auto tarPos : ringMap[key[tar]]) {
int curStep = minDis(tarPos, markPos); // rotate
curStep += 1; // write
memo[tar][markPos] = min(
memo[tar][markPos],
dfsMemo(tar + 1, tarPos, ringMap, key, memo) + curStep
);
}
// cout << "memo ing: " << tar << ", " << markPos << ": " << memo[tar][markPos] << endl;
return memo[tar][markPos];
}
int minDis(int tarPos, int markPos) {
int gt = max(tarPos, markPos);
int lt = min(tarPos, markPos);
return min(gt - lt, lt + ringLen - gt);
}
};
// choosing: right
int tmpRightCover = min(
// r的监控器对r的两个子节点都有监控作用,于是直接去计算两个子节点的子节点
1 + minCameraCover(r_rll) + minCameraCover(r_rlr) + minCameraCover(r_rrl) + minCameraCover(r_rrr) + minCameraCover(r_l),
min(
// r的监控器对r的两个子节点中的右孩子有监控作用,于是计算方式变为算右孩子两个子节点加上左侧节点
// partly ignore, will not put cam on r_rr, may on r_r
1 + minCameraCover(r_rrl) + minCameraCover(r_rrr) + minCameraCover(r_rl) + minCameraCover(r_l),
// r的监控器对r的两个子节点中的左孩子有监控作用,于是计算方式变为算左孩子两个子节点加上右侧节点
// partly ignore, will not put cam on r_rl, may on r_l
1 + minCameraCover(r_rll) + minCameraCover(r_rlr) + minCameraCover(r_rr) + minCameraCover(r_l)
)
);
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int level = 0;
unordered_map<TreeNode* , int> memo;
int minCameraCover(TreeNode* root) {
++level;
if(nullptr == root) {
return 0;
}
if(nullptr == root->left && nullptr == root->right) {
return 1;
}
// dp:
TreeNode* r_l = root->left;
TreeNode* r_r = root->right;
TreeNode* r_ll = getL(r_l);
TreeNode* r_lr = getR(r_l);
TreeNode* r_rl = getL(r_r);
TreeNode* r_rr = getR(r_r);
TreeNode* r_lll = getL(r_ll);
TreeNode* r_llr = getR(r_ll);
TreeNode* r_lrl = getL(r_lr);
TreeNode* r_lrr = getR(r_lr);
TreeNode* r_rll = getL(r_rl);
TreeNode* r_rlr = getR(r_rl);
TreeNode* r_rrl = getL(r_rr);
TreeNode* r_rrr = getR(r_rr);
int cover_r_lll = getFromMemo(r_lll);
int cover_r_llr = getFromMemo(r_llr);
int cover_r_lrl = getFromMemo(r_lrl);
int cover_r_lrr = getFromMemo(r_lrr);
int cover_r_rll = getFromMemo(r_rll);
int cover_r_rlr = getFromMemo(r_rlr);
int cover_r_rrl = getFromMemo(r_rrl);
int cover_r_rrr = getFromMemo(r_rrr);
int cover_r_ll = getFromMemo(r_ll);
int cover_r_lr = getFromMemo(r_lr);
int cover_r_rl = getFromMemo(r_rl);
int cover_r_rr = getFromMemo(r_rr);
int cover_r_l = getFromMemo(r_l);
int cover_r_r = getFromMemo(r_r);
// // choosing: root
// int tmpRootCover = min(
// // min(
// // do not ignore
// 1 + minCameraCover(r_ll) + minCameraCover(r_lr) + minCameraCover(r_rl) + minCameraCover(r_rr),
// // 1 + minCameraCover(r_l) + minCameraCover(r_r)
// // ),
// // partly ignore root choosen
// min(
// 1 + minCameraCover(r_ll) + minCameraCover(r_lr) + minCameraCover(r_r),
// 1 + minCameraCover(r_rl) + minCameraCover(r_rr) + minCameraCover(r_l)
// )
// );
int tmpRootCover = min(
1 + cover_r_ll + cover_r_lr + cover_r_rl + cover_r_rr,
min(
1 + cover_r_ll + cover_r_lr + cover_r_r,
1 + cover_r_rl + cover_r_rr + cover_r_l
)
);
// // choosing: right
// int tmpRightCover = min(
// // don't ignore, will not put cam on r_rl, r_rr
// 1 + minCameraCover(r_rll) + minCameraCover(r_rlr) + minCameraCover(r_rrl) + minCameraCover(r_rrr) + minCameraCover(r_l),
// min(
// // partly ignore, will not put cam on r_rr, may on r_r
// 1 + minCameraCover(r_rrl) + minCameraCover(r_rrr) + minCameraCover(r_rl) + minCameraCover(r_l),
// // partly ignore, will not put cam on r_rl, may on r_l
// 1 + minCameraCover(r_rll) + minCameraCover(r_rlr) + minCameraCover(r_rr) + minCameraCover(r_l)
// )
// );
int tmpRightCover = min(
1 + cover_r_rll + cover_r_rlr + cover_r_rrl + cover_r_rrr + cover_r_l,
min(
1 + cover_r_rrl + cover_r_rrr + cover_r_rl + cover_r_l,
1 + cover_r_rll + cover_r_rlr + cover_r_rr + cover_r_l
)
);
// // choosing: left
// int tmpLeftCover = min(
// 1 + minCameraCover(r_lll) + minCameraCover(r_llr) + minCameraCover(r_lrl) + minCameraCover(r_lrr) + minCameraCover(r_r),
// min(
// 1 + minCameraCover(r_ll) + minCameraCover(r_lrl) + minCameraCover(r_lrr) + minCameraCover(r_r),
// 1 + minCameraCover(r_lr) + minCameraCover(r_lll) + minCameraCover(r_llr) + minCameraCover(r_r)
// )
// );
int tmpLeftCover = min(
1 + cover_r_lll + cover_r_llr + cover_r_lrl + cover_r_lrr + cover_r_r,
min(
1 + cover_r_ll + cover_r_lrl + cover_r_lrr + cover_r_r,
1 + cover_r_lr + cover_r_lll + cover_r_llr + cover_r_r
)
);
return min(tmpRootCover, min(tmpLeftCover, tmpRightCover));
}
TreeNode* getR(TreeNode* root) {
if(nullptr == root) {
return nullptr;
} else {
return root->right;
}
}
TreeNode* getL(TreeNode* root) {
if(nullptr == root) {
return nullptr;
} else {
return root->left;
}
}
int getFromMemo(TreeNode* root) {
if(memo.end() == memo.find(root)) {
memo[root] = minCameraCover(root);
}
return memo[root];
}
};
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- cepb.cn 版权所有 湘ICP备2022005869号-7
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务