c语言闯算法--常用技巧

embedded/2025/3/14 7:30:59/

双指针

类别:

  • 同向快慢指针
    • 异常情况,慢指针才动
  • 双向指针
    • 视情况,左右指针动

最长无重复子串

int max(int a, int b){if(a < b){return b;}else{return a;}
}
int lengthOfLongestSubstring(char* s) {int count[300];for(int i = 0; i < 300; i++){count[i] = 0;}int l = 0;// printf("%d", strlen(s));int res = 0;int len = strlen(s);for(int i = 0; i < len; i++){count[s[i] - ' ']++;while(count[s[i] - ' '] > 1){count[s[l] - ' ']--;l++;// printf("%d---\n", l);}// printf("%d\n", i - l + 1);res = max(res, i - l + 1);}return res;
}

字符串字母异位词

/*** Note: The returned array must be malloced, assume caller calls free().*/
int* findAnagrams(char* s, char* p, int* returnSize) {//有返回,先定义int lenS = strlen(s);int* res = malloc(lenS * sizeof(int));*returnSize = 0;//字母异位词就是:找词频一样的int cntP[26];int cntS[26];for(int i = 0; i < 26; i++){cntP[i] = 0;cntS[i] = 0;}//先统计p中的词频int lenP = strlen(p);for(int i = 0; i < lenP; i++){cntP[p[i] - 'a']++;}for(int i = 0; i < 26; i++){printf("%d ",cntP[i]);}//滑动窗口统计s中的int l = 0;for(int r = 0; r < lenS; r++){cntS[s[r] - 'a']++;if(r - l + 1 == lenP){//现在窗口大小一致bool flag = true;for(int i = 0; i < 26; i++){if(cntP[i] != cntS[i]) flag = false;}if(flag){res[(*returnSize)++] = l;}}// cntS[s[l] - 'a']--;//只有窗口大小超过才需要减掉左边if(r - l + 1 >= lenP){cntS[s[l] - 'a']--;l++;}}return res;}

最长不重复子序列

#include<stdio.h>
#include<stdlib.h>#define N 100010int cnt[N];//模拟哈希表,记录词频int max(int a, int b){if(a > b){return a;}else{return b;}
}int main(){int n; scanf("%d", &n);int* tmp = malloc((n + 1) * sizeof(int));int x;for(int i = 0; i < n; i++){scanf("%d", &x);tmp[i] = x;}int l = 0; int r = 0;int res = 0;for(; r < n; r++){cnt[tmp[r] - 1]++;while(l <= r && cnt[tmp[r] - 1] > 1){cnt[tmp[l] - 1]--;l++;}res = max(res, r - l + 1);}printf("%d", res);return 0;
}

数组元素的目标和

#include<stdio.h>
#include<stdlib.h>int main(){int n, m, x;scanf("%d %d %d", &n, &m, &x);int* A = malloc((n + 1) * sizeof(int));int* B = malloc((m + 1) * sizeof(int));int tmp;for(int i = 0; i < n; i++){scanf("%d", &tmp);A[i] = tmp;}for(int i = 0; i < m; i++){scanf("%d", &tmp);B[i] = tmp;}int l = 0; int r = m - 1;int sum;while(l < n && r >= 0){sum = A[l] + B[r];if(sum > x){r--;}else if(sum < x){l++;}else{printf("%d %d", l , r);break;}}return 0;
}

判断子序列

#include<stdio.h>
#include<stdlib.h>int main(){int n, m;scanf("%d %d", &n, &m);int* a = malloc((n + 1) * sizeof(int));int* b = malloc((m + 1) * sizeof(int));int x;for(int i = 0; i < n; i++){scanf("%d", &x);a[i] = x;}for(int i = 0; i < m; i++){scanf("%d", &x);b[i] = x;}int cnt = 0;//b数组更长for(int i = 0; i < m; i++){if(cnt < n && b[i] == a[cnt]){cnt++;}}if(cnt == n){printf("Yes");}else{printf("No");}return 0;
}

并查集

合并集合

#include<stdio.h>
#include<stdlib.h>#define N 100010int f[N];int find(int a){if(a != f[a]) f[a] = find(f[a]);return f[a];
}int main(){int n, m;scanf("%d %d", &n, &m);//并查集初始化for(int i = 1; i <= n; i++){f[i] = i;}for(int i = 0; i < m; i++){char op[2];scanf("%s", op);if(op[0] == 'M'){int a, b;scanf("%d %d", &a, &b);int f1 = find(a);int f2 = find(b);if(f1 != f2){f[f1] = f2;}}else{int a, b;scanf("%d %d", &a, &b);if(find(a) != find(b)){printf("No\n");}else{printf("Yes\n");}}}return 0;
}

连通块的数量

#include<stdio.h>#define N 100010int f[N];
int cnt[N];int find(int a){if(a != f[a]) f[a] = find(f[a]);return f[a];
}int main(){int n, m;scanf("%d %d", &n, &m);for(int i = 1; i <= n; i++){f[i] = i;cnt[i] = 1;}for(int i = 0; i < m; i++){char op[3];scanf("%s", op);if(op[0] == 'C'){int a, b;scanf("%d %d", &a, &b);int f1 = find(a);int f2 = find(b);if(f1 != f2){cnt[f2] += cnt[f1];f[f1] = f2;}}else if(op[0] == 'Q' && op[1] == '1'){int a, b;scanf("%d %d", &a, &b);int f1 = find(a);int f2 = find(b);if(f1 != f2){printf("No\n");}else{printf("Yes\n");}}else{int a;scanf("%d", &a);printf("%d\n", cnt[find(a)]);}}return 0;
}

Tire树

Trie字符串统计

#include<stdio.h>#define N 200100//模拟树
int t[N][26];
int idx;//记录单词数
int cnt[N];//记录每次的字符串
char str[N];void insert(){int p = 0; //表示根节点for(int i = 0; str[i] != '\0'; i++){//遍历整个字符串int x = str[i] - 'a';if(!t[p][x]) t[p][x] = ++idx;//节点不存在,创建p = t[p][x];//让指针往下走,遍历完字符串}//到达最终的节点cnt[p]++;//表示以此节点为结束的字符串个数
}void query(){int p = 0;for(int i = 0; str[i] != '\0'; i++){int x = str[i] - 'a';// if(!t[p][x]) break;//不存在if(!t[p][x]) {//不能break,否则还是会输出打印printf("0\n");return;}p = t[p][x];}//最终找到了printf("%d\n", cnt[p]);
}int main(){int n;scanf("%d", &n);char op[2];for(int i = 0; i < n; i++){scanf("%s", op);scanf("%s", str);if(op[0] == 'I'){insert();}else{query();}}return 0;
}

异或最大值

//trie树不仅可以存字符串,还可以存二进制数#include<stdio.h>#define  N 100010int a[N];//模拟树
int t[N * 32][2];
int idx;int max(int a, int b){if(a > b){return a;}else{return b;}
}void insert(int a){int p = 0; for(int i = 31; i >= 0; i--){//存二进制需要从高位开始int x = a >> i & 1;if(!t[p][x]) t[p][x] = ++idx;p = t[p][x];}
}int query(int a){int p = 0; int res = 0;for(int i = 31; i >= 0; i--){int x = a >> i & 1;if(t[p][!x]){//要求异或值最大,所以每一次都需要找相反值p = t[p][!x];res += 1 << i;//有相反值,异或得1}else{p = t[p][x];//不存在相反之,异或得0}}return res;
}int main(){int n; scanf("%d", &n);int x;for(int i = 0; i < n; i++){scanf("%d", &x);a[i] = x;insert(a[i]);}int res = 0; //遍历每一个数的异或值,取最大for(int i = 0; i < n; i++){res = max(res, query(a[i]));}printf("%d", res);return 0;
}

实现trie

#define N 100010typedef struct {int t[N][26];bool flag[N];int idx;
} Trie;Trie* trieCreate() {Trie* t = malloc(sizeof(Trie));memset(t, 0, sizeof(Trie));  // 初始化所有值为 0return t;
}void trieInsert(Trie* obj, char* word) {int p = 0;for(int i = 0; word[i] != '\0'; i++){int x = word[i] - 'a';if(!(obj->t[p][x])) obj->t[p][x] = ++(obj->idx);p = obj->t[p][x];}obj->flag[p] = true;
}bool trieSearch(Trie* obj, char* word) {int p = 0;for(int i = 0; word[i] != '\0'; i++){int x = word[i] - 'a';if(!obj->t[p][x]) return false;p = obj->t[p][x];}return obj->flag[p];
}bool trieStartsWith(Trie* obj, char* prefix) {int p = 0;for(int i = 0; prefix[i] != '\0'; i++){int x = prefix[i] - 'a';if(!obj->t[p][x]) return false;p = obj->t[p][x];}return true;
}void trieFree(Trie* obj) {free(obj);
}/*** Your Trie struct will be instantiated and called as such:* Trie* obj = trieCreate();* trieInsert(obj, word);* bool param_2 = trieSearch(obj, word);* bool param_3 = trieStartsWith(obj, prefix);* trieFree(obj);
*/


http://www.ppmy.cn/embedded/172440.html

相关文章

红帆 iOffice M2 移动端密码爆破的渗透测试思路,绕过客户端实现Burpsuite批量跑,分享渗透思路,共建网络安全

一、本文概述 今天来自于领导的一个需求,需要对甲方的红帆 ioffice M2进行一次渗透测试【有授权书的】,拿到对应的APP和接口以后,我发现了进行不下去的一个关键点,他家的OA只有APP端,没有Web端,而且密码被加密了。 二、开始分析 红帆 iOffice M2,在登录的过程中,涉及…

自定义日志回调函数实现第三方库日志集成:从理论到实战

一、应用场景与痛点分析 在开发过程中&#xff0c;我们经常会遇到以下场景&#xff1a; 日志格式统一&#xff1a;第三方库使用自己的日志格式&#xff0c;导致系统日志混杂&#xff0c;难以统一管理和分析。日志分级过滤&#xff1a;需要动态调整第三方库的日志输出级别&…

完全二叉树节点的数量 平衡二叉树

1.给出一个完全二叉树&#xff0c;求出该树的节点个数 #include <bits/stdc.h> using namespace std; struct TreeNode{ int val; TreeNode* left; TreeNode* right; TreeNode(int x) { valx; leftNULL; rightNULL; } …

无人机快速发展,无人机反制如何应对?

无人机&#xff0c;即无人驾驶飞机&#xff0c;是一种不搭载驾驶员、依靠遥控或预设程序自主飞行的航空器。随着技术的不断进步和应用领域的不断拓展&#xff0c;无人机已经在军事、民用、商业等多个领域展现出巨大的潜力和价值。 无人机反制是指采取一系列措施来防范、干扰、…

Linux入门 2025 全面整理终端 Bash、Vim 命令速记

Linux入门 2025 超详细全面整理 Bash、Vim 基础命令速记 刚面对高级感满满的 终端窗口是不是有点懵&#xff1f;于是乎&#xff0c;这份手册就是为你准备的高效学习指南&#xff01;我把那些让人头大的系统设置、记不住的命令都整理成了对你更友好的格式&#xff0c;让你快速学…

基于STM32F407ZGT6的硬件平台,(可选CubeMX) + PlatformIO软件开发的FreeRTOS部署指南

目录 前言 使用CubeMX生成代码的FreeRTOS移植方案 时钟选择 在Middlewares中选择FreeRTOS的版本支持 其他外设的支持 封装自己配置的任务 生成PIO代码 修改platformio.ini 第一步&#xff1a;指定我们的源码文件夹 第二步&#xff0c;解决FPU的选择问题 非CubeMX的Fr…

46. HarmonyOS NEXT 登录模块开发教程(一):模态窗口登录概述

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT 登录模块开发教程&#xff08;一&#xff09;&#xff1a;模态窗口登录概述 文章目录 HarmonyOS NEXT 登录模块开发教程&#xff0…

ADB报错:daemon not running...

ADB报错&#xff1a;daemon not running… 解决步骤: ADB【问题】程序报错&#xff1a;daemon not running; starting now at tcp:5037 【原因】5037端口被占用 【方法】找出5037端口占用的应用&#xff0c;关闭掉该应用进程 【解决方案】打开cmd命令窗口&#xff0c;首先找出占…