1给定一个字符串str,只由'X'和'.'两种字符构成
'X'表示墙,不能放灯,也不需要点亮;'.'表示居民点,可以放灯,需要点亮
如果灯放在i位置,可以让i-1,i和i+1三个位置被点亮
返回如果点亮str中所有需要点亮的位置,至少需要几盏灯
从左往右依次考虑是否放灯不放灯
若遍历到的点是x,则直接跳过
若遍历到的点是i,则先判断下一个什么情况:
下一个超范围,灯得在该处放,灯数加
下一个是x,灯得到该处放,灯加,然后i跳两格
下一个是.,灯数加,无论i+2是什么,情况都一样,之后i跳三格
#include <string>
using namespace std;
int minLight1(string road) {
int i = 0;
int light = 0;
while (i < road.length()) {
if (road[i] == 'X') {
i++;
} else {
light++;
if (i + 1 == road.length()) {
break;
} else {
if (road[i + 1] == 'X') {
i = i + 2;
} else {
i = i + 3;
}
}
}
}
return light;
}
2一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲,给你每一个项目开始的时间和结束的时间
你来安排宣讲的日程,要求会议室进行的宣讲的场次最多,返回最多的宣讲场次
策略:每次都选结束时间最早的
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class program {
public:
int start;
int end;
program(int a,int b):start(a),end(b){}
};
//暴力法:每个会议都去尝试 arr表示还剩下多少会议
int process(vector<program>& arr, int done, int timeline)
{
if (arr.empty())
return done;
int maxcount = done;
for (int i = 0; i < arr.size(); i++)
{
if (arr[i].start >= timeline)
{
vector<program> next(arr);
next.erase(next.begin() + i);
maxcount = max(maxcount, process(next, done + 1, arr[i].end));
}
return maxcount;
}
}
int bestArrange1(vector<program>& arr)
{
if (arr.empty())
return 0;
return process(arr, 0, 0);
}
//贪心法:每次都选择结束时间最晚的会议
int bestArrange2(vector<program>& programs) {
sort(programs.begin(), programs.end(), [](const program& a, const program& b) {
return a.end < b.end;
});
int timeLine = 0;
int result = 0;
for (const program& program : programs) {
if (timeLine <= program.start) {
result++;
timeLine = program.end;
}
}
return result;
}
3一块金条切成两半,是需要花费和长度数值一样的铜板
比如长度为20的金条,不管怎么切都要花费20个铜板,一群人想整分整块金条,怎么分最省铜板?
例如,给定数组{10,20,30},代表一共三个人,整块金条长度为60,金条要分成10,20,30三个部分。
如果先把长度60的金条分成10和50,花费60;再把长度50的金条分成20和30,花费50;一共花费110铜板
但如果先把长度60的金条分成30和30,花费60;再把长度30金条分成10和20,花费30;一共花费90铜板
哈夫曼编码问题:每次从小根堆里面弹出两个最小数,然后合并
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int lessMoney(vector<int>& arr)
{
priority_queue<int, vector<int>, greater<int>> p;
for (int i = 0; i < arr.size(); i++)
{
p.push(arr[i]);
}
int sum = 0, cur = 0;
while (p.size() > 1)
{
cur = p.top(), p.pop();
cur += p.top(), p.pop();
sum += cur;
p.push(cur);
}
return sum;
}
#include <vector>
#include <climits>
using namespace std;
int lessMoney1(vector<int>& arr) {
if (arr.empty()) {
return 0;
}
return process(arr, 0);
}
int process(vector<int>& arr, int pre) {
if (arr.size() == 1) {
return pre;
}
int ans = INT_MAX;
for (int i = 0; i < arr.size(); i++) {
for (int j = i + 1; j < arr.size(); j++) {
vector<int> newArr = copyAndMergeTwo(arr, i, j);
ans = min(ans, process(newArr, pre + arr[i] + arr[j]));
}
}
return ans;
}
vector<int> copyAndMergeTwo(vector<int>& arr, int i, int j) {
vector<int> ans;
for (int arri = 0; arri < arr.size(); arri++) {
if (arri != i && arri != j) {
ans.push_back(arr[arri]);
}
}
ans.push_back(arr[i] + arr[j]);
return ans;
}
4
输入正数数组costs、正数数组profits、正数K和正数M
costs[i]表示i号项目的花费
profits[i]表示i号项目在扣除花费之后还能挣到的钱(利润)
K表示你只能串行的最多做k个项目
M表示你初始的资金
说明:每做完一个项目,马上获得的收益,可以支持你去做下一个项目,不能并行的做项目。
输出:最后获得的最大钱数
#include <vector>
#include <queue>
#include <functional>
using namespace std;
class program {
public:
int p;//表示一个项目的利润
int c;//表示一个项目的花费
program(int a,int b):p(a),c(b){}
};
//按花费少的比较器建立小根堆
class mincost {
public:
bool operator()(program a, program b)
{
return a.c > b.c;
}
};
class maxprofit {
public:
bool operator()(program a, program b)
{
return a.p < b.p;
}
};
int findMaximizedCapital(int k, int w, vector<int>& profits, vector<int>& capital)
{
priority_queue<program, vector<program>, mincost> minc;
priority_queue<program, vector<program>, maxprofit> maxp;
for (int i = 0; i < profits.size(); i++)
{
minc.push(program(profits[i],capital[i]));
}
for (int i = 0; i < k; i++)
{
while (!minc.empty() && minc.top().c <= w)
{
maxp.push(minc.top());
minc.pop();
}
if (maxp.empty())
{
return w;
}
w += maxp.top(). p;
maxp.pop();
}
return w;
}
5 并查集的实现
功能:查找是否在一个集合,合并两个所在的集合,实现了o(1)的查找
#include <unordered_map>
#include <vector>
#include <stack>
using namespace std;
// 每个数据封装一个节点
template<typename V>
class node {
public:
V value;
node(V a) : value(a) {} // 使用成员初始化列表初始化成员变量
};
template <typename V>
class unionfind {
public:
unordered_map<V, node<V>*> nodes;
unordered_map<node<V>*, node<V>*> parents;
unordered_map<node<V>*, int> sizeMap;
unionfind(vector<V> arr) {
for (V a : arr) {
node<V>* cur = new node<V>(a);
nodes[a] = cur;
parents[cur] = cur;
sizeMap[cur] = 1;
}
}
// 查找过程的优化:把沿途节点都直接挂在代表节点下面
node<V>* findfather(node<V>* cur) {
stack<node<V>*> path;
while (cur != parents[cur]) {
path.push(cur);
cur = parents[cur];
}
while (!path.empty()) {
parents[path.top()] = cur;
path.pop();
}
return cur;
}
bool issameset(V a, V b) {
return findfather(nodes[a]) == findfather(nodes[b]);
}
void union(V a, V b) {
node<V>* ahead = findfather(nodes[a]);
node<V>* bhead = findfather(nodes[b]);
if (ahead != bhead) {
int asize = sizeMap[ahead]; // 使用sizeMap[ahead]
int bsize = sizeMap[bhead]; // 使用sizeMap[bhead]
node<V>* big = asize > bsize ? ahead : bhead;
node<V>* small = big == ahead ? bhead : ahead;
parents[small] = big;
sizeMap[big] = asize + bsize;
sizeMap.erase(small);
}
}
int sets() {
return sizeMap.size();
}
};