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

双指针

类别:

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

最长无重复子串

objectivec 复制代码
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;
}

字符串字母异位词

objectivec 复制代码
/**
 * 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;


}

最长不重复子序列

objectivec 复制代码
#include<stdio.h>
#include<stdlib.h>

#define N 100010

int 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;
}

数组元素的目标和

objectivec 复制代码
#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;
}

判断子序列

objectivec 复制代码
#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;
}

并查集

合并集合

objectivec 复制代码
#include<stdio.h>
#include<stdlib.h>

#define N 100010

int 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;
}

连通块的数量

objectivec 复制代码
#include<stdio.h>

#define N 100010

int 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字符串统计

objectivec 复制代码
#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;
}

异或最大值

objectivec 复制代码
//trie树不仅可以存字符串,还可以存二进制数

#include<stdio.h>

#define  N 100010

int 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

objectivec 复制代码
#define N 100010

typedef struct {
    int t[N][26];
    bool flag[N];
    int idx;
} Trie;


Trie* trieCreate() {
    Trie* t = malloc(sizeof(Trie));
    memset(t, 0, sizeof(Trie));  // 初始化所有值为 0

    return 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);
*/
相关推荐
爱装代码的小瓶子44 分钟前
数据结构之队列(C语言)
c语言·开发语言·数据结构
爱喝矿泉水的猛男2 小时前
非定长滑动窗口(持续更新)
算法·leetcode·职场和发展
YuTaoShao2 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
YouQian7722 小时前
Traffic Lights set的使用
算法
快乐飒男2 小时前
哈希表(c语言)
c语言·哈希算法·散列表
go54631584654 小时前
基于深度学习的食管癌右喉返神经旁淋巴结预测系统研究
图像处理·人工智能·深度学习·神经网络·算法
aramae4 小时前
大话数据结构之<队列>
c语言·开发语言·数据结构·算法
大锦终4 小时前
【算法】前缀和经典例题
算法·leetcode
想变成树袋熊4 小时前
【自用】NLP算法面经(6)
人工智能·算法·自然语言处理
cccc来财5 小时前
Java实现大根堆与小根堆详解
数据结构·算法·leetcode