代码学习总结(二)
代码学习总结(二)
这个系列的博客是记录下自己学习代码的历程,有来自平台上的,有来自笔试题回忆的,主要基于 C++ 语言,包括题目内容,代码实现,思路,并会注明题目难度,保证代码运行结果
1 质数密钥
简单
质数密钥
组合与匹配
第一行输入两个正整数 n n n , m m m ( l ≤ n ≤ 20 l ≤n≤ 20 l≤n≤20 ; 1 ≤ m ≤ 14 1≤ m ≤ 14 1≤m≤14 )代表片段数量、片段长度。此后 n n n 行,第 i i i 行输入一个长度为 m m m ,仅由字符’0’和’1’组成的字符串 S S S ;表示第 i i i 个片段。
我们截获了 n n n 条片段,每一个片段均由 m m m 个字符组成,字符为’0’或者’1’。
你可以选择一些片段,将它们做按位或运算后,生成一个完整的密钥。根据加密算法的需求,合成后的密钥在转换为十进制的数值后必须恰好为一个质数,才能符合安全系统的运算要求(质数在许多公钥密码体系中具有特殊意义)。
请你设计一个程序,帮助安全专家确定:
任意选取片段,能得到多少个不同的质数密钥?
示例输入输出:
输入:m = 4, n = 4, {“0110”, “1110”, “1111”, “1011”}
输出:1
思路解析:
- 首先把二进制的字符片段转化为数字,以便于判断
- 之后对所有可能的组合进行搜索,在构造素数时,也采用记忆的模式,找到为素数的组合
- 返回最终的搜索存储后结果
本地 debug
代码
#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <cmath>
using namespace std;
// 判断一个数是否是质数
bool is_prime(int num) {
if (num < 2) return false;
for (int i = 2; i <= sqrt(num); ++i)
if (num % i == 0)
return false;
return true;
}
// 核心逻辑函数:统计可以组合出的不同质数“钥匙”的个数
int count_prime_keys(int n, int m, const vector<string>& binary_strings) {
vector<int> fragments(n);
// 将二进制字符串转换为整数
for (int i = 0; i < n; ++i) {
int val = 0;
for (char c : binary_strings[i]) {
val = (val << 1) | (c - '0');
}
fragments[i] = val;
}
set<int> prime_keys;
// 枚举所有非空子集并计算“钥匙”
for (int mask = 1; mask < (1 << n); ++mask) {
int key = 0;
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
key |= fragments[i];
}
}
if (is_prime(key)) {
prime_keys.insert(key);
}
}
return prime_keys.size();
}
int main() {
int n, m;
n = 4;
m = 4;
vector<string> binary_strings = {"0110", "1110", "1111", "1011"};
int result = count_prime_keys(n, m, binary_strings);
cout << result << endl;
return 0;
}
上述代码的运行结果为

可用于提交的代码
// 判断一个数是否是质数
bool is_prime(int num) {
if (num < 2) return false;
for (int i = 2; i <= sqrt(num); ++i)
if (num % i == 0)
return false;
return true;
}
// 核心逻辑函数:统计可以组合出的不同质数“钥匙”的个数
int count_prime_keys(int n, int m, const vector<string>& binary_strings) {
vector<int> fragments(n);
// 将二进制字符串转换为整数
for (int i = 0; i < n; ++i) {
int val = 0;
for (char c : binary_strings[i]) {
val = (val << 1) | (c - '0');
}
fragments[i] = val;
}
set<int> prime_keys;
// 枚举所有非空子集并计算“钥匙”
for (int mask = 1; mask < (1 << n); ++mask) {
int key = 0;
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
key |= fragments[i];
}
}
if (is_prime(key)) {
prime_keys.insert(key);
}
}
return prime_keys.size();
}
2 N 矩阵
中等
字典树
单词拆分
对于给定的
n
n
n 行
m
m
m 列的矩阵,每一个位置要么是大写字母’N’要么是大写字母’Z’
现在,你需要选择一整行和一整列(即选中一个"十"字形区域),将这个区域中的全部大写字母’Z替换为’N’,使得替换后的矩阵中,"N"的数量尽可能多。
直接输出这个最大数量。
注意:词典中的同一个单词可能在分段中被重复使用多次。
示例输入输出:
输入: n = 2; m = 2; {“NN”, “ZZ”}
输出: 2
思路解析:
- 在拿到矩阵时,首先可以先检查每行每列中 N 的数量
- 然后就是枚举搜索每个交叉点的N的数量了
- N 的数量最多的,就是答案
graph TD
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([开始]):::startend --> B(初始化 n、m 和 matrix):::process
B --> C(调用 getMaxNCountAfterReplacement 函数):::process
C --> D(初始化 rowNCount 数组,大小为 n,初始值为 0):::process
D --> E(初始化 colNCount 数组,大小为 m,初始值为 0):::process
E --> F(初始化 totalN = 0):::process
F --> G(初始化 i = 0):::process
G --> H{i < n?}:::decision
H -->|否| I(初始化 maxTotalN = 0):::process
H -->|是| J(初始化 j = 0):::process
J --> K{j < m?}:::decision
K -->|否| L(i 加 1):::process
K -->|是| M{matrix_i_j == 'N'?}:::decision
M -->|否| N(j 加 1):::process
M -->|是| O(rowNCount'i' 加 1):::process
O --> P(colNCount'j' 加 1):::process
P --> Q(totalN 加 1):::process
Q --> N
N --> K
L --> H
I --> R(初始化 r = 0):::process
R --> S{r < n?}:::decision
S -->|否| T(返回 maxTotalN):::process
S -->|是| U(初始化 c = 0):::process
U --> V{c < m?}:::decision
V -->|否| W(r 加 1):::process
V -->|是| X(currentN = rowNCount'r' + colNCount'c'):::process
X --> Y{matrix'r''c' == 'N'?}:::decision
Y -->|否| Z(maxTotalN = max'maxTotalN, currentN'):::process
Y -->|是| AA(currentN 减 1):::process
AA --> Z
Z --> AB(c 加 1):::process
AB --> V
W --> S
T --> AC(输出结果):::process
AC --> AD([结束]):::startend
本地 debug
代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// 核心处理函数
int getMaxNCountAfterReplacement(int n, int m, const vector<string>& matrix) {
vector<int> rowNCount(n, 0); // 每行N的数量
vector<int> colNCount(m, 0); // 每列N的数量
int totalN = 0;
// 统计每行和每列的N数量
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (matrix[i][j] == 'N') {
rowNCount[i]++;
colNCount[j]++;
totalN++;
}
}
}
int maxTotalN = 0;
// 枚举每一个交叉点(行r和列c)
for (int r = 0; r < n; ++r) {
for (int c = 0; c < m; ++c) {
int currentN = rowNCount[r] + colNCount[c];
if (matrix[r][c] == 'N') {
// 如果交叉点本身是'N',加了两次,要减一
currentN -= 1;
}
maxTotalN = max(maxTotalN, currentN);
}
}
return maxTotalN;
}
int main() {
int n, m;
n = 2; m = 2;
vector<string> matrix{"NN", "ZZ"};
int result = getMaxNCountAfterReplacement(n, m, matrix);
cout << result << endl;
return 0;
}
上述代码的运行结果为

可用于提交的代码
int getMaxNCountAfterReplacement(int n, int m, const vector<string>& matrix) {
vector<int> rowNCount(n, 0); // 每行N的数量
vector<int> colNCount(m, 0); // 每列N的数量
int totalN = 0;
// 统计每行和每列的N数量
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (matrix[i][j] == 'N') {
rowNCount[i]++;
colNCount[j]++;
totalN++;
}
}
}
int maxTotalN = 0;
// 枚举每一个交叉点(行r和列c)
for (int r = 0; r < n; ++r) {
for (int c = 0; c < m; ++c) {
int currentN = rowNCount[r] + colNCount[c];
if (matrix[r][c] == 'N') {
// 如果交叉点本身是'N',加了两次,要减一
currentN -= 1;
}
maxTotalN = max(maxTotalN, currentN);
}
}
return maxTotalN;
}
这里的题目是 来自笔试中的回忆版本 ,感兴趣的同学们可以看看解题思路,每日二题,努力加油😉!!!