算法 刷题 蓝桥杯 百题 其二 蓝桥杯 fufhaha 2025-03-09 2025-04-06 刷题 1 2 3 4 5 6 1. 注意循环中i,j的使用有没有错误2. 注意dfs中标记数组的清空3. dfs参数问题,遍历的起始值要注意4. 数组定义的时候要检查[][],而不是[,]5. 在有些题目中即使它是数字1 ,0 ,但是他说的是字符输入也要改成字符,不然可能因为间隔问题输入失败6. 每次每组搜索前一定要重置标记数组memset (vis, 0 , sizeof (vis));
1.高精度问题 0R 格式 - 蓝桥云课
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 vector <int >a;int t=0 ;for (int i=0 ;i<len;++i){ a[i]=2 *a[i]+t; if (a[i]>=10 ){ t=a[i]/10 ; a[i]%=10 ; } else { t=0 ; } } if (t){ a.push_back(t); len++; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 string s;int pos=s.find('.' );s.erase(pos,n); reverse(s.begin(),s.end()); vector <int > a;a.push_back(n);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <bits/stdc++.h> #define N 10010 using namespace std ; int main () { string s; int n; vector <int >a; cin >>n>>s; reverse(s.begin(),s.end()); int pos=s.find('.' ); s.erase(pos,1 ); int len=s.size(); for (int i=0 ;i<len;++i){ a.push_back(s[i]-'0' ); } while (n--){ int t=0 ; for (int i=0 ;i<len;++i){ a[i]=2 *a[i]+t; if (a[i]>=10 ){ t=a[i]/10 ; a[i]%=10 ; } else { t=0 ; } } if (t){ a.push_back(t); len++; } } if (a[pos-1 ]>=5 ){ if (pos==len-1 ){ a.push_back(1 ); } else { a[pos]++; } } for (int i=len-1 ;i>=pos;--i){ cout <<a[i]; } return 0 ; }
2.关于最大公约数和最小公倍数的关系 0宝石组合 - 蓝桥云课
3.关于多个限制条件的dfs问题 0数字接龙 - 蓝桥云课
1 2 3 4 5 string s;s.empty(); to_string(i);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <bits/stdc++.h> using namespace std ; int n,k;int a[20 ][20 ];int dx[8 ]={-1 ,-1 ,0 ,1 ,1 ,1 ,0 ,-1 };int dy[8 ]={0 ,1 ,1 ,1 ,0 ,-1 ,-1 ,-1 };int vis[20 ][20 ]={0 };string res;void dfs (int x,int y,int pre,int step,string s) { if (step==n*n && x==n && y==n){ if (res.empty()){ res=s; } return ; } for (int i=0 ;i<8 ;++i){ int nx=x+dx[i]; int ny=y+dy[i]; if (nx<1 || nx>n || ny<1 || ny>n || vis[nx][ny]){ continue ; } if (i==1 && vis[x-1 ][y] && vis[x][y+1 ]) continue ; else if (i==3 && vis[x+1 ][y] && vis[x][y+1 ]) continue ; else if (i==5 && vis[x+1 ][y] && vis[x][y-1 ]) continue ; else if (i==7 && vis[x-1 ][y] && vis[x][y-1 ]) continue ; if ((pre+1 ==a[nx][ny] && a[nx][ny]<k) || (pre+1 ==k && a[nx][ny]==0 )){ vis[nx][ny]=1 ; dfs(nx,ny,a[nx][ny],step+1 ,s+to_string(i)); if (!res.empty()){ return ; } vis[nx][ny]=0 ; } } } int main () { cin >>n>>k; for (int i=1 ;i<=n;++i){ for (int j=1 ;j<=n;++j){ cin >>a[i][j]; } } string tmp; vis[1 ][1 ]=1 ; dfs(1 ,1 ,0 ,1 ,tmp); if (!res.empty()) cout <<res; else { cout <<-1 ; } return 0 ; }
4.在不同条件下的存在解问题 0飞机降落 - 蓝桥云课
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <bits/stdc++.h> using namespace std ; typedef struct { int t; int d; int l; }p; int n;p pl[20 ]; int vis[20 ]={0 };int se;void dfs (int num,int last) { if (n==num){ se=1 ; return ; } for (int i=1 ;i<=n;++i){ if (vis[i]) continue ; if (last>pl[i].t+pl[i].d) continue ; vis[i]=1 ; dfs(num+1 ,max(pl[i].t,last)+pl[i].l); vis[i]=0 ; } return ; } int main () { int t; cin >>t; while (t--){ memset (vis, 0 , sizeof (vis)); cin >>n; se=0 ; for (int i=1 ;i<=n;++i){ cin >>pl[i].t>>pl[i].d>>pl[i].l; } dfs(0 ,0 ); if (se==1 ){ cout <<"YES" ; } else { cout <<"NO" ; } } return 0 ; }
5.dfs环套子岛屿问题 0岛屿个数 - 蓝桥云课
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 #include <bits/stdc++.h> using namespace std ; int t, m, n;int s[62 ][62 ] = {0 };int sea_vis[62 ][62 ] = {0 };int land_vis[62 ][62 ] = {0 }; int sum;int dx[4 ] = {0 ,1 ,0 ,-1 };int dy[4 ] = {1 ,0 ,-1 ,0 };void mark_sea (int x, int y) { if (x < 0 || x > m+1 || y < 0 || y > n+1 ) return ; if (sea_vis[x][y] || s[x][y] != 0 ) return ; sea_vis[x][y] = 1 ; for (int i=0 ; i<4 ; ++i){ int nx = x + dx[i]; int ny = y + dy[i]; mark_sea(nx, ny); } } void check_land (int x, int y, int & valid) { if (x < 1 || x > m || y < 1 || y > n) return ; if (land_vis[x][y] || s[x][y] != 1 ) return ; land_vis[x][y] = 1 ; for (int i=0 ; i<4 ; ++i){ int nx = x + dx[i]; int ny = y + dy[i]; if (sea_vis[nx][ny]) valid = 1 ; } for (int i=0 ; i<4 ; ++i){ int nx = x + dx[i]; int ny = y + dy[i]; check_land(nx, ny, valid); } } int main () { cin >> t; while (t--) { memset (s, 0 , sizeof (s)); memset (sea_vis, 0 , sizeof (sea_vis)); memset (land_vis, 0 , sizeof (land_vis)); sum = 0 ; cin >> m >> n; for (int i=1 ; i<=m; ++i){ string row; cin >> row; for (int j=1 ; j<=n; ++j){ s[i][j] = row[j-1 ] - '0' ; } } mark_sea(0 , 0 ); for (int i=1 ; i<=m; ++i){ for (int j=1 ; j<=n; ++j){ if (s[i][j] == 1 && !land_vis[i][j]){ int valid = 0 ; check_land(i, j, valid); sum += valid; } } } cout << sum << "\n" ; } return 0 ; }
6.链表的增删改查 好的,下面是用 C 语言实现链表增删改查的分步解释和代码示例:
📌 链表基础结构 c
复制
1 2 3 4 typedef struct Node { int data; // 数据域 struct Node* next; // 指针域(指向下一个节点) } Node;
1. 增加节点(增) 头插法(插入到链表头部) c
复制
1 2 3 4 5 6 Node* insertAtHead(Node* head, int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next = head; // 新节点指向原头节点 return newNode; // 返回新头节点 }
尾插法(插入到链表尾部) c
复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Node* insertAtTail(Node* head, int value) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next = NULL; if (head == NULL) { return newNode; // 链表为空时直接返回新节点 } Node* current = head; while (current->next != NULL) { current = current->next; // 找到最后一个节点 } current->next = newNode; // 将新节点链接到末尾 return head; }
2. 删除节点(删) 删除特定值的节点 c
复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 Node* deleteNode(Node* head, int value) { if (head == NULL) return NULL; // 如果要删除的是头节点 if (head->data == value) { Node* temp = head; head = head->next; free(temp); return head; } // 查找要删除的节点及其前驱 Node* prev = head; Node* current = head->next; while (current != NULL) { if (current->data == value) { prev->next = current->next; free(current); break; } prev = current; current = current->next; } return head; }
3. 修改节点(改) c
复制
1 2 3 4 5 6 7 8 9 10 11 void updateNode(Node* head, int oldValue, int newValue) { Node* current = head; while (current != NULL) { if (current->data == oldValue) { current->data = newValue; // 直接修改数据域 return; } current = current->next; } printf("未找到值为 %d 的节点\n", oldValue); }
4. 查找节点(查) c
复制
1 2 3 4 5 6 7 8 9 10 Node* searchNode(Node* head, int value) { Node* current = head; while (current != NULL) { if (current->data == value) { return current; // 返回找到的节点指针 } current = current->next; } return NULL; // 未找到返回 NULL }
🛠️ 工具函数:打印链表 c
复制
1 2 3 4 5 6 7 8 void printList(Node* head) { Node* current = head; while (current != NULL) { printf("%d -> ", current->data); current = current->next; } printf("NULL\n"); }
📝 完整示例代码 c
复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* next; } Node; // 插入、删除、修改、查找函数实现(同上) int main() { Node* head = NULL; // 插入测试 head = insertAtHead(head, 3); head = insertAtHead(head, 2); head = insertAtHead(head, 1); head = insertAtTail(head, 4); printList(head); // 输出: 1 -> 2 -> 3 -> 4 -> NULL // 删除测试 head = deleteNode(head, 2); printList(head); // 输出: 1 -> 3 -> 4 -> NULL // 修改测试 updateNode(head, 3, 99); printList(head); // 输出: 1 -> 99 -> 4 -> NULL // 查找测试 Node* found = searchNode(head, 99); if (found != NULL) { printf("找到值为 99 的节点\n"); } return 0; }
🔧 关键注意事项
内存管理 :每次 malloc
后必须对应 free
,避免内存泄漏。
边界条件 :处理空链表、头节点/尾节点等特殊情况。
指针操作 :修改链表结构时注意正确调整指针指向。
错误处理 :检查 malloc
是否成功(示例中未展示,实际需添加)。
如果需要更详细的某个操作解释或更多变种操作(如中间插入、按位置删除),可以告诉我! 😊
好的!以下是链表的 中间插入(在指定位置或节点后插入) 和 按位置删除 的详细实现和解释:
1. 中间插入节点(指定位置插入) 假设链表的索引从 0
开始,例如要在位置 pos
插入节点。
c
复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // 在链表的第 pos 个位置插入节点(从 0 开始计数) Node* insertAtPosition(Node* head, int value, int pos) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next = NULL; // 如果插入到头部(pos=0) if (pos == 0) { newNode->next = head; return newNode; // 返回新头节点 } // 找到插入位置的前驱节点 Node* current = head; for (int i = 0; i < pos - 1 && current != NULL; i++) { current = current->next; } // 如果位置无效(例如链表长度不足) if (current == NULL) { printf("插入位置无效!\n"); free(newNode); // 释放未使用的节点内存 return head; } // 插入新节点 newNode->next = current->next; current->next = newNode; return head; }
2. 按位置删除节点 删除链表中指定位置 pos
的节点。
c
复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 Node* deleteAtPosition(Node* head, int pos) { if (head == NULL) { printf("链表为空!\n"); return NULL; } // 删除头节点(pos=0) if (pos == 0) { Node* temp = head; head = head->next; free(temp); return head; } // 找到要删除节点的前驱 Node* prev = head; Node* current = head; for (int i = 0; i < pos && current != NULL; i++) { prev = current; current = current->next; } // 如果位置无效 if (current == NULL) { printf("删除位置无效!\n"); return head; } // 调整指针并释放内存 prev->next = current->next; free(current); return head; }
3. 在指定节点后插入(另一种中间插入方式) 假设已知某个节点 targetNode
,在其后插入新节点。
c
复制
1 2 3 4 5 6 7 8 9 10 11 void insertAfterNode(Node* targetNode, int value) { if (targetNode == NULL) { printf("目标节点不存在!\n"); return; } Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = value; newNode->next = targetNode->next; targetNode->next = newNode; }
🛠️ 使用示例 c
复制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int main() { Node* head = NULL; // 创建初始链表: 1 -> 2 -> 3 head = insertAtTail(head, 1); head = insertAtTail(head, 2); head = insertAtTail(head, 3); printList(head); // 输出: 1 -> 2 -> 3 -> NULL // 在位置 1 插入 99 head = insertAtPosition(head, 99, 1); printList(head); // 输出: 1 -> 99 -> 2 -> 3 -> NULL // 在节点值为 2 的节点后插入 88 Node* target = searchNode(head, 2); insertAfterNode(target, 88); printList(head); // 输出: 1 -> 99 -> 2 -> 88 -> 3 -> NULL // 删除位置 2 的节点(值为 2) head = deleteAtPosition(head, 2); printList(head); // 输出: 1 -> 99 -> 88 -> 3 -> NULL return 0; }
🔧 关键点总结
中间插入 :
需要遍历链表找到插入位置的前驱节点。
注意处理边界条件(如插入到头部或尾部)。
确保插入位置的有效性(避免越界)。
按位置删除 :
同样需要遍历找到前驱节点。
释放内存前务必调整指针,防止链表断裂。
时间复杂度 :
插入和删除操作的时间复杂度为 **O(n)**(需要遍历链表)。
如果频繁按位置操作,可以考虑使用双向链表优化。
如果有其他具体场景或细节需要补充,请告诉我! 😊