代码教训总结

2019/10/2
小心对待每一个赋值表达式。

在写一个 BFS 时,我写下了这样的代码

        while (!que.empty()) {
            auto p = que.front();
            que.pop();
            int d = maze[p.first][p.second]; // maze should be dis
            rng (i, 0, 4) {
                int x = p.first + dx[i], y = p.second + dy[i];
                if (x >= 0 && x < R && y >= 0 && y < C && dis[x][y] > d + 1) {
                    dis[x][y] = d + 1;
                    que.emplace(x, y);
                }
            }
        }

其中 int d = maze[p.first][p.second]; 写错了。maze 代表地图,应当是 dis


2019/9/27
std::next_permutation 枚举全排列时,要保证初始排列是字典序最小的排列。

今天做网易游戏的校招笔试。有个问题需要枚举 "ASDFGH" 这六个字符的全排列。
一开始我是这样写的

string s = "ASDFGH";
do {
  // do something with s
} while (next_permutation(s.begin(), s.end()));

结果只得了 60% 的分数。

上述代码错误之处在于它并未枚举所有排列。初始排列 "ASDFGH" 并不是字典序最小的排列,这么写只是枚举了字典序大于等于 "ASDFGH" 的所有排列。

正确写法

string s = "ASDFGH";
sort(s.begin(), s.end());
// 或者 string s = "ADFGHS";
do {
  // do something with s
} while (next_permutation(s.begin(), s.end()));

2019/9/23
调用 std::unique 或者 std::unique_copy(since C++17)之前,一定要确保数组是有序的(往往需要先调用 std::sort)。


2018/5/19
用整数表示集合时,判断第 i 个元素是否属于集合 S,可以用 if (S & 1 << i)if (S >> i & 1) 。判断第 i 个元素是否不属于集合 S 时,我一般会用 if ( (S & 1 << i) == 0 ),但是这样写有一个坏处:常常会忘记 bitwise and(&)算符的优先级低于 == 算符。有两个更好的写法可以避免这个问题,第一个是 if ( !(S & 1 << i) ),因为我知道 ! 算符的优先级是很高的;第二个是 if ( ~S & 1 << i ) 这个写法不需要括号,可以说是很优雅了 XD,但是由于要多算 ~S, 是否会比较慢?(玄学) 。

Remark:&^|&&|| 都比 == 优先级低。


2018/4/21
WA 了首先要检查输入数据的类型是否跟数据范围匹配。


2018/4/18
在某个问题中,需要实现以下过程。
维护一个二元组(std::pair)的集合。
pair 的第二维表示 unique 且 const 的 ID,第一维只减不增,并且始终大于等于 $0$ 。
每次从集合中取出第一维为 $0$ 的 pair(并将其从集合中删除,保证这样的 pair 存在),然后将集合中的某些 pair 的第一维减 $1$ 。

我的写法:

  • std::set> 支持取出第一维是 $0$ 的 pair
  • 用一个数组存储每个 ID 对应的 std::pair::first 的当前值。
  • 若 set 中第一个元素的第一维与数组中的值不相等,则更新

这种做法是有问题的,因为并不能确任当前 set 中的第一个元素的第一维的实际值就是 $0$ 。
正确的做法是即时更新 set 中的元素(先 erase 旧的,再 insert 新的),而且上述数组也是不必要的


2018/1/1
对 $m$ 取模的运算,一定保证最后结果在 $0$ 到 $m-1$ 之间。

DP:要考虑是否有某些状态虽然是个合法状态,但是始终没被计算到。

2018/1/2
变量命名:若用 #include 引入头文件,prevnext 这两个名字都会引起变量名冲突,可以用 prvnxt 代替。

2018/1/3
不要滥用 for 循环,用 while 循环合适时应当用 while

2018/4/2
“把简单的问题搞复杂”、“很短的代码就能解决,我的代码却很长”;这类错误是不能容忍的。

2018/4/3
用 range-for 遍历容器 a 时,若要修改容器中的元素则应该用 for(auto &x: a) 。不修改时,也可以这么用,所以用 range-for 时,总是采用引用的形式。

你可能感兴趣的:(代码教训总结)