单例模式
#include <iostream>
#include <vector>
#include <mutex>
using namespace std;
mutex mtx;
class singleton {
public:
shared_ptr<singleton> getInstance() {
if (only_ = nullptr) {
unique_lock<mutex> lock(mtx);
{
only_ = make_shared<singleton>();
}
}
return only_;
}
void dosomething() {
cout << "do something ..." << "\n";
}
private:
singleton() = default;
~singleton() = default;
singleton(const singleton&) = delete;
singleton& operator=(const singleton&) = delete;
shared_ptr<singleton> only_;
};
注意的几个问题:
- public 中开放的是获取实例的函数,和 dosomething
- 将构造函数以及其他,和实例指针(引用)存放在 private
- 为了线程安全最好在创建实例时上锁
迭代器失效的情况
要求: 找到一个数组中的奇数,并全部删除
应该用双指针,但是他考察的是迭代器失效的情景,也就是 erase 返回的是下一个迭代器
迭代器版本
#include <iostream>
#include <vector>
namespace test {
using namespace std;
void test1() {
vector<int> v = {1, 2, 3, 4, 5};
for (auto it = v.begin(); it != v.end();) {
if (*(it) & 1) {
it = v.erase(it);
} else {
++it;
}
}
ranges::for_each(v.begin(), v.end(), [](int i) { std::cout << i << " "; });
}
}
int main() {
test::test1();
}
左右指针:
#include <iostream>
#include <vector>
namespace test {
using namespace std;
void test1() {
vector<int> v = {1, 2, 3, 4, 5};
int l = 0, r = v.size() - 1;
while (l <= r) {
if (!v.at(l) & 1) {
++l;
} else if (v.at(r) & 1) {
--r;
} else {
swap(v[l], v[r]);
++l;
--r;
}
}
v.resize(l);
ranges::for_each(v.begin(), v.end(), [](int i) { std::cout << i << " "; });
}
}
int main() {
test::test1();
}
两种方法的比较:
方法 | 时间复杂度 | 空间复杂度 | 适用场景 | 优点 | 缺点 |
---|---|---|---|---|---|
左右指针 + resize | O(n) | O(1) | 适用于不关心元素顺序的情况 | 高效,只需一次遍历 | 会改变元素的相对顺序 |
erase 逐个删除 | O(n²)(最坏情况) | O(1) | 适用于需要保持顺序的情况 | 保持原有顺序 | 删除操作导致元素移动,效率较低 |