寒假CS每日打卡 Feb.2nd
技術標籤:2021寒假每日打卡演算法C++寒假學習LeetCodeAcwing
演算法部分
1.Acwing 入門組每日一題
題目:數獨檢查
數獨是一種流行的單人遊戲。目標是用數字填充9x9矩陣,使每列,每行和所有9個非重疊的3x3子矩陣包含從1到9的所有數字。每個9x9矩陣在遊戲開始時都會有部分數字已經給出,通常有一個獨特的解決方案。
給定完成的N2∗N2數獨矩陣,你的任務是確定它是否是有效的解決方案。有效的解決方案必須滿足以下條件:
每行包含從1到N2的每個數字,每個數字一次。
每列包含從1到N2的每個數字,每個數字一次。
將N2∗N2矩陣劃分為N2個非重疊N∗N子矩陣。 每個子矩陣包含從1到N2的每個數字,每個數字一次。
輸入格式
第一行包含整數T,表示共有T組測試資料。
每組資料第一行包含整數N。
接下來N2行,每行包含N2個數字(均不超過1000),用來描述完整的數獨矩陣。
輸出格式
每組資料輸出一個結果,每個結果佔一行。
結果表示為“Case #x: y”,其中x是組別編號(從1開始),如果給定矩陣是有效方案則y是Yes,否則y是No。
資料範圍
1≤T≤100,
3≤N≤6
輸入樣例:
3
3
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
4 2 6 8 5 3 7 9 1
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9
3
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
3
5 3 4 6 7 8 9 1 2
6 7 2 1 9 5 3 4 8
1 9 8 3 4 2 5 6 7
8 5 9 7 6 1 4 2 3
7 1 3 9 2 4 8 5 6
9 6 1 5 3 7 2 8 4
2 8 7 4 1 9 6 3 5
3 4 5 2 8 6 1 7 9
輸出樣例:
Case #1: Yes
Case #2: No
Case #3: No
題解:
依次檢查每行、每列、每個小九宮格是否滿足條件,使用 bool 陣列 記錄元素的出現情況。
程式碼:
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 50;
bool vis[MAXN][MAXN];
int g[MAXN][MAXN];
void check(int r, int c, bool &op, int cnt, int size){
for(int i = r; i < r + size; i ++)
for(int j = c; j < c + size; j ++){
if(vis[cnt][g[i][j]])
op = false;
vis[cnt][g[i][j]] = true;
}
}
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i ++){
bool op = true;
int size;
cin >> size;
for(int i = 0; i < size * size; i ++)
for(int j = 0; j < size *size; j ++){
cin >> g[i][j];
if(g[i][j] < 1 || g[i][j] > size * size)
op = false;
}
//檢查行
memset(vis, false, sizeof(vis));
for(int i = 0; i < size * size && op; i ++)
for(int j = 0; j < size * size && op; j ++){
if(vis[i][g[i][j]])
op = false;
vis[i][g[i][j]] = true;
}
//檢查列
memset(vis, false, sizeof(vis));
for(int i = 0; i < size * size && op; i ++)
for(int j = 0; j < size * size && op; j ++){
if(vis[i][g[j][i]])
op = false;
vis[i][g[j][i]] = true;
}
//檢查 size * size 個子矩陣
int cnt = 0;
memset(vis, false, sizeof(vis));
for(int i = 0; i < size && op; i ++)
for(int j = 0; j < size && op; j ++)
check(i * size, j * size, op, cnt, size), cnt ++;
if(op)
cout << "Case #" << i << ": Yes" << endl;
else
cout << "Case #" << i << ": No" << endl;
}
return 0;
}
2.Acwing 提高組每日一題
題目:數獨簡單版
數獨是一種傳統益智遊戲,你需要把一個 9×9 的數獨補充完整,使得圖中每行、每列、每個 3×3 的九宮格內數字 1∼9 均恰好出現一次。請編寫一個程式填寫數獨。
輸入格式
輸入共 9 行,每行包含一個長度為 9 的字串,用來表示數獨矩陣。
其中的每個字元都是 1∼9 或 .(表示尚未填充)。
輸出格式
輸出補全後的數獨矩陣。
資料保證有唯一解。
輸入樣例:
.2738…1.
.1…6735
…29
3.5692.8.
…
.6.1745.3
64…
9518…7.
.8…6534.
輸出樣例:
527389416
819426735
436751829
375692184
194538267
268174593
643217958
951843672
782965341
題解:
dfs深搜求解,注意剪枝,也就是考慮這一行、這一列以及小九宮格數字的出現情況,需要陣列記錄。此外,把二維座標對映到一維,使用公式 r * 邊長 + c 即可將二維座標對映到一維,而且沒有衝突。
#include <iostream>
using namespace std;
const int MAXN = 10;
char g[MAXN][MAXN];
bool hang[MAXN][MAXN], lie[MAXN][MAXN], sub[MAXN][MAXN];
void dfs(int le){
//遞迴出口
if(le == 81){
for(int i = 0; i < 9; i ++)
cout << g[i] << endl;
return ;
}
//從一維座標得到行和列
int r = le / 9;
int c = le % 9;
//已經擺好了,則進行下一層遞迴
if(g[r][c] != '.'){
dfs(le + 1);
return;
}
//有1 - 9 种放法
for(int i = 1; i <= 9; i ++){
if(hang[r][i] || lie[c][i] || sub[(r / 3) * 3 + c / 3][i])
continue;
g[r][c] = i + '0';
hang[r][i] = true;
lie[c][i] = true;
sub[(r / 3) * 3 + c / 3][i] = true;
dfs(le + 1);
//回溯之後恢復現場
hang[r][i] = false;
lie[c][i] = false;
sub[(r / 3) * 3 + c / 3][i] = false;
g[r][c] = '.';
}
}
int main(){
for(int i = 0; i < 9; i ++)
cin >> g[i];
//預處理 行、列小九宮格資訊
for(int i = 0; i < 9; i ++)
for(int j = 0; j < 9; j ++){
if(g[i][j] != '.'){
hang[i][g[i][j] - '0'] = true;
lie[j][g[i][j] - '0'] = true;
sub[(i / 3) * 3 + j / 3][g[i][j] - '0'] = true;
}
}
dfs(0);
return 0;
}
3.LeetCode 每日一題
題目:替換後的最長重複字元
給你一個僅由大寫英文字母組成的字串,你可以將任意位置上的字元替換成另外的字元,總共可最多替換 k 次。在執行上述操作後,找到包含重複字母的最長子串的長度。
注意:字串長度 和 k 不會超過 104。
示例 1:
輸入:s = “ABAB”, k = 2
輸出:4
解釋:用兩個’A’替換為兩個’B’,反之亦然。
示例 2:
輸入:s = “AABABBA”, k = 1
輸出:4
解釋:
將中間的一個’A’替換為’B’,字串變為 “AABBBBA”。
子串 “BBBB” 有最長重複字母, 答案為 4。
題解:
將題目抽象為維護一個區間,當滿足條件就擴大這個區間,否則縮小區間,在這個頭尾擴充套件的過程中維護最大值,一個區間滿足能滿足轉變為同一字元的條件是 區間長度 <= K + 區間內最大的同一字元出現次數,因為只需要把其他字元都轉變為那個出現次數最多的字元即可。
class Solution {
public:
int characterReplacement(string s, int k) {
int res = 0, le = 0, ri = 0, ans = 0;
vector<int> cnt(26, 0);
while(ri < s.length()){
cnt[s[ri] - 'A'] ++;
//更新歷史最大單字元出現次數
res = max(res, cnt[s[ri] - 'A']);
//判斷是否滿足條件
if(ri - le + 1 - k > res){
//不滿足,則需要移動頭指標,同時將頭指標對應的字元出現次數 -1
cnt[s[le] - 'A'] --;
++ le;
}
++ ri;
}
return ri - le;
}
};
4.春招衝刺 - 從前序與中序遍歷序列構造二叉樹
題目:
根據一棵樹的前序遍歷與中序遍歷構造二叉樹。
注意:
你可以假設樹中沒有重複的元素。
例如,給出
前序遍歷 preorder = [3,9,20,15,7]
中序遍歷 inorder = [9,3,15,20,7]
返回如下的二叉樹:
3
/ \
9 20
/ \
15 7
題解:
經典的資料結構題,做完本題可以嘗試根據後序和中序遍歷構造二叉樹。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
//key: value of node | value : index in inorder traversal
unordered_map<int, int> map;
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int cur = 0;
for(int i = 0; i < inorder.size(); i ++)
map[inorder[i]] = i;
return dfs(preorder, cur, inorder, 0, preorder.size() - 1);
}
TreeNode *dfs(vector<int> &pre, int &cur, vector<int> &in, int le, int ri){
if(le > ri)
return nullptr;
//使用map能提高效率,mid為中序遍歷對應的下標
int mid = map[pre[cur]];
// for(int i = le; i <= ri; i ++)
// if(pre[cur] == in[i]){
// mid = i;
// break;
// }
TreeNode *root = new TreeNode(pre[cur]);
++ cur;
//遞迴求左子樹和右子樹
root -> left = dfs(pre, cur, in, le, mid - 1);
root -> right = dfs(pre, cur, in, mid + 1, ri);
return root;
}
};
5.春招衝刺 - 階乘後的零
題目:
給定一個整數 n,返回 n! 結果尾數中零的數量。
示例 1:
輸入: 3
輸出: 0
解釋: 3! = 6, 尾數中沒有零。
示例 2:
輸入: 5
輸出: 1
解釋: 5! = 120, 尾數中有 1 個零.
說明: 你演算法的時間複雜度應為 O(log n) 。
題解:
細細品下面的程式碼,作為校招面試題也不錯哦 ><
class Solution {
public:
int trailingZeroes(int n) {
int ans = 0;
for(int i = 5; i <= n; i *= 5){
ans += n /i;
}
return ans;
}
};
書籍部分
圖解TCP|IP 第2章 ✔
MYSQL必知必會 第9 - 12章 ✔
PS.
- 明天看一下markdown語法
- 有時間看一下閆氏dp分析法,做一下總結