题目:服务器连接方式包括直接相连,间接连接。 A 和 B 直接连接, B 和 c 直接连接,则 A 和 c 间接连接。直接连接和间接连接都可以发送广播。
给出一个 N * N 数组,代表 N 个服务器, matrix[i][j] == 1 ,则代表 i 和 j 直接连接;不等于 1 时,代表 i 和 j 不直接连接。 matrix[i][i]== 1 ,即自己和自己直接连接。 matrix[i][j]==matrix[j][i] 。计算初始需要给几台服务器广播,才可以使侮个服务器都收到广播。
输入描述: n * n 矩阵,
[[1,1,0],[1,1,0],[0,0,1]]
1
输出描述:整数
2
int main () {
//vector> v{{1,0,1,0,1,1},{0,1,0,1,0,0},{1,0,1,0,0,0},{0,1,0,1,0,0},{1,0,0,0,1,0},{1,0,0,0,0,1}};
vector<vector<int>> v{{1,0,1,0,1,1},{0,1,0,0,0,0},{1,0,1,0,0,0},{0,0,0,1,0,0},{1,0,0,0,1,0},{1,0,0,0,0,1}};
unordered_map<int,set<int>> a;
auto len = v.size();
for (int i = 0;i<len;i++) {
for (int j=0;j<len;j++) {
if (v[i][j] == 1) {
a[i].insert(j);
}
}
}
for (auto iter = a.begin(); iter != a.end();iter++) {
int num = iter->first;
set<int> tmp =iter->second;
for (int j : tmp) {
if (num != j) {
a[j].insert(tmp.begin(),tmp.end());
}
}
}
set<set<int>> ret;
for (auto iter = a.begin(); iter != a.end();iter++) {
set<int> tmp =iter->second;
ret.insert(tmp);
}
cout << ret.size() << endl;
return 0;
}
心路历程:用什么数据结构有时比算法重要,数据结构也能体现解决方法。
开始拿到题目,纸上画了画人工是怎么思考的,第一感觉是想到做过的一道题,一个矩阵,某元素为1的话会像炸弹那样令跟它同一行和同一列的元素都变成1,新生成的1不会有这个效果。画格子画了会没啥感觉,又想到这题从描述就天然是个图问题,用dfs递归下?但是天然的对dfs比较排斥,估计写不来,并没有做过多思考。再画两下,突然就画出了题解中的数据结构,map, 接下来就比较容易了。中间也考虑过用两层vector,一想内层的大小不一致不能用, 题解中答案写完后试了下内层的vector也是可变的,大小能任意变,这题数据结构改成vector
经验:
1.遇到报错一定要多检查括号写错没
ret.insert(tmp); 这句手误打成了 ret.insert< tmp >; 没检查出来,报错为:
reference to non-static member function must be called
2.对于迭代器使用不熟练,int num = iter->first; 写这块时不确定是
int num = *iter->first;
或者 int num = *(iter)->first)
或者 int num = *(iter->first); 浪费了几分钟时间
首先是优先级要记牢:(优先级越高越先)
第一优先级: :: 仅此一个作用域解析符
第二优先级:()[] -> .
第三优先级:* &
迭代器:vector中 *iter就能访问到数据元素了,而map中不需要 * ,auto p = iter->first; 就能访问到第一个元素了
vector<int> bb{1,2,3,4};
for (auto i = bb.begin();i!=bb.end();i++) {
cout << *i << " ";
}
输出 : 1 2 3 4
unordered_map<int,set<int>> a;
for (auto iter = a.begin(); iter != a.end();iter++) {
int num = iter->first;
set<int> tmp =iter->second;
}
string str = "12388sf";
int ret = 0;
to_int(str, ret);
bool to_int(const string& str, int& ret) {
int len = str.length();
std::string::size_type sz;
bool flag = false;
try {
ret = stoi(str,&sz);
if (sz == len) {
flag = true;
}
} catch (std::invalid_argument&) {
} catch (std::out_of_range&) { // {}内可以是空语句的
} catch (std::exception& e) {
cout << e.what() << endl;
}
//} catch (...) {
//}
return flag;
}
注意点:
stoi的原型为:
int stoi (const string& str, size_t* idx = 0, int base = 10);
第二个参数为能转成数字的下一位的下标,是指针。第三个参数为要将第一个参数中数字用什么进制解释。如果str的第一个字符不是字符0-9,则会出异常,报 invalid_argument , 如果范围超过了int,则报 out_of_range 异常,如果这两点都没问题,而 sz 的大小和 length 不相等,则说明数字后面还有非数字字符。所以这个函数用起来还是比较麻烦的,得自己check。
另一个用法举例:
std::string str_hex = "40c3";
int i_hex = std::stoi (str_hex,nullptr,16);
std::cout << str_hex << ": " << i_hex << '\n';
输出:
40c3: 16579
题目:实现字符串分割算法split(str,delim),传入待分割字符串和分割字符,返回数组,如果delim参数不传,则对字符串逐个分割。
比如调用split(“abcbebb”,‘b’),返回为[“a”,“c”,“e”],调用split(‘abcd’),返回[‘a’,‘b’,‘c’,d’]
std::vector<std::string> split_string(const std::string& s, const char flag = ' ') {
if (s.empty()) {
return {};
}
std::vector<std::string> str_vec;
if (flag != '\0') { // 注意点一:用'\0'表示空字符,表示参数二没传入。这个一度阻塞了思路。同时记住'\0'很特殊,是ascii表的第一个,即是基准
istringstream iss(s);
std::string temp;
while (getline(iss, temp, flag)) {
if (!temp.empty()) {
str_vec.push_back(temp);
}
}
} else {
for(char i : s) {
string t;
t.push_back(i); // 注意点二:将char转成string的方法:往新申请的string里push_back(char)即可。另外注意不要用to_string,这个传入的参数是int float double等数字型的变量
str_vec.push_back(t);
}
}
return char_vec;
}
题目:给定一个单词列表,将这个列表编码成一个索引字符串 S 与一个索引列表 A。
例如,如果这个列表是 [“time”, “me”, “bell”],将其表示为 S = “time#bell#” 和 indexes = [0, 2, 5]。
对于每一个索引,可以通过从字符串 S 中索引的位置开始读取字符串,直到 “#” 结束,来恢复之前的单词列表。
输入描述:数组。
输出描述:成功对给定单词列表进行编码的最小字符串长度
class Solution {
public:
int minimumLengthEncoding(vector<string>& words) {
sort(words.begin(), words.end(), [](const string& a, const string& b) -> bool {return a.length() > b.length();});
string ret = words[0] + "#";
for (int i = 1; i < words.size(); ++i) {
auto found = ret.find(words[i] + "#");
if (found == string::npos) {
ret += words[i] + "#";
}
}
return ret.length();
}
};
思路很简单,按长度依次处理是关键,另外需要注意题目要求必须以“#”结束,所以比如 time# 可以匹配 me,不能匹配 ti, 为此将每个word加上“#”后才进行find。解法的时空效率不怎么高
题目:某个打印机根据打印队列执行打印任务。打印任务分为九个优先级,分别采用数字1~9表示,数字越大优先级越高。打印机每次从队列头部取出第一个任务A,然后检查队列余下任务中有没有比A优先级更高的任务,如果有比A优先级高的任务,则将任务A放到队列尾部,否则执行任务A的打印。请编写一个程序,根据输入的打印队列,输出实际打印顺序
struct mydata{
int n;
int pos;
mydata(int i, int j):n(i),pos(j) {}
};
bool comp(const mydata& a, const mydata& b) {
return a.n < b.n;
}
int main () {
int n = 0;
while(cin>>n) {
vector<int> p;
deque<mydata> v;
for(int i=0;i<n;i++) {
int p = 0;
cin >> p;
mydata m(p,i);
v.push_back(m);
}
while(!v.empty()) {
auto m = *max_element(v.begin(), v.end(), comp);
int nn = m.n;
if (nn == v.front().n) {
p.push_back(m.pos);
v.pop_front();
} else {
auto t = v.front();
v.push_back(t);
v.pop_front();
}
}
for(auto i : p) {
cout << i << " ";
}
cout << endl;
}
return 0;
}
输入
6
1 1 9 1 1 1
输出
2 3 4 5 0 1