【算法笔记题解】《算法笔记知识点记录》第四章——算法初步2——哈希

简介: 【算法笔记题解】《算法笔记知识点记录》第四章——算法初步2——哈希

由于放原题的话文章实在太长,所以题多的话我只放思路和题解,大家请前往相应的网站查看题目呀0.0


🧑🏻作者简介:一个从工业设计改行学嵌入式的年轻人

✨联系方式:2201891280(QQ)

📔源码地址:https://gitee.com/xingleigao/algorithm-notes

⏳全文大约阅读时间: 30min

全文目录

🍕4.2小节——算法初步->哈希

问题 A: 谁是你的潜在朋友

问题 B: 分组统计

问题 C: Be Unique (20)

问题 D: String Subtraction (20)

B1029 旧键盘 (20 分)

B1033 旧键盘打字 (20 分)

B1038 统计同成绩学生 (20 分)

A1092 To Buy or Not to Buy (20 分)

B1042 字符统计 (20 分)

B1043 输出PATest (20 分)

A1041 Be Unique (20 分)

A1050 String Subtraction (20 分)

B1005 继续(3n+1)猜想 (25 分)

A1048 Find Coins (25 分)

🍕4.2小节——算法初步->哈希

地址合集:《算法笔记》4.2小节——算法初步->哈希


问题 A: 谁是你的潜在朋友

直接hash表统计就好了。


#include <cstdio>
#include <cstring>
int main(){
    int m,n;
    const char zero[6] = "BeiJu";
    while(scanf("%d %d",&n, &m) != EOF){
        int hash[m+1];    //书籍的hash表
        int peo[n]; //人员列表
        memset(hash,0,sizeof(hash));
        for(int i = 0;i < n ;++i)   scanf("%d",&peo[i]),hash[peo[i]]++;
        for(int i = 0;i < n ;++i)   
            if(hash[peo[i]] > 1)    printf("%d\n",hash[peo[i]] - 1);
            else        printf("%s\n",zero);
    }
    return 0;
}

问题 B: 分组统计

建个二维hash表就好了,但是要注意的是,可能有的组号一个元素都没有是不需要打印的,大坑,调了半小时。。。


#include <cstdio>
#include <cstring>
int hash[101][2000];    //保存每组的数字个数 注意到组号不为0  可以利用0组保存所有的元素表
int num[110];   //保存所有的数字
int main(){
    int m, n;
    while(scanf("%d" , &m) != EOF){
        while(m--){
            memset(hash, 0, sizeof(hash));
            scanf("%d", &n);
            int max_num = 0;
            for(int i = 0;i < n;++i){
                scanf("%d",&num[i]),hash[0][num[i]] = 1;//读入第一行元素
                if(num[i] > max_num)    max_num = num[i];
            }
            int max_group = 0;
            for(int i = 0;i < n;++i){   //读入第二行元素并设置相应的hash表
                int tmp;
                if(max_group < tmp) max_group = tmp;
                scanf("%d", &tmp), hash[tmp][num[i]]++;
                hash[tmp][0] = 1;       //记录出现的组号    会跳组号 尼玛 离谱-。-
            }
            for(int i = 1;i <= max_group;++i){
                if(hash[i][0]){
                    printf("%d={",i);//输出前面的数据
                    for(int j = 0;j < max_num;j++){
                        if(hash[0][j])  printf("%d=%d,",j,hash[i][j]);
                    }
                    printf("%d=%d}\n",max_num,hash[i][max_num]);//输出后面的数据
                }
            }
        }
    }
    return 0;
}


问题 C: Be Unique (20)

借用宇哥的话,这个就是paper tiger,花里胡哨的,其实很简答的。


#include <cstdio>
#include <cstring>
short hash[10010];
char *s = "None";
int num[1000005];
int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        memset(hash, 0, sizeof(hash));
        for(int i = 0;i < n;i++)    scanf("%d",&num[i]),hash[num[i]]++;    //读入数据,设置hahs表
        int j ;
        for(j = 0;j < n;j++)    
            if(hash[num[j]] == 1){
                printf("%d\n",num[j]);
                break;
            }
        if(j == n)  printf("%s\n",s);
    }
    return 0;
}

问题 D: String Subtraction (20)

#include <iostream>
#include <cstring>
using namespace std;
char s1[10008],s2[10008];
unsigned char Hash[128];
int main(){
    while(cin.getline(s1,10008)){
        cin.getline(s2, 10008);
        memset(Hash, 0, sizeof(Hash));
        for(int i = 0;s2[i];++i)   Hash[s2[i]] = 1;
        for(int i = 0;s1[i];++i)    if(!Hash[s1[i]]) putchar(s1[i]);
        puts("");
    }
}


B1029 旧键盘 (20 分)

地址:A1084 Broken Keyboard (20 分) B1029 旧键盘 (20 分)

就是hash表记录一下坏的按键控制只输出一次就好了。


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int Hash[128];
int main(){
    char s1[88],s2[88];
    while(cin.getline(s1,88)){
        cin.getline(s2,88);
        memset(Hash, 0, sizeof(Hash));//全局变量初始化
        for(int i = 0,j = 0;s1[i];i++){
            if(s1[i] != s2[j]){ //判断是否输入成功
                unsigned char tmp = (s1[i] <= 'z' && s1[i] >= 'a') ? s1[i] - ' ':s1[i];//转成大写
                if(!Hash[tmp]){ 
                    Hash[tmp] = 1;
                    putchar(tmp);
                }
            }
            else j++;//没坏往后走
        }
        puts("");   //补个格式
    }
    return 0;
}


B1033 旧键盘打字 (20 分)

地址:B1033 旧键盘打字 (20 分)

其实思路和上面的差不多,记录坏按键,坏的不打印就好了。


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int Hash[128];
int main(){
    char s1[88];
    while(cin.getline(s1,88)){
        memset(Hash, 0, sizeof(Hash));//全局变量初始化
        char TOP = 1;
        for(int i = 0;s1[i];++i){   //写Hash表
            if(s1[i] == '+')    TOP = 0;
            else if(s1[i] <= 'Z' && s1[i] >= 'A')   Hash[s1[i] + ' '] = 1;
            else Hash[s1[i]] = 1;
        }
        char c;
        while((c = getchar()) != '\n'){
            if(c >= 'A' && c <= 'Z')    //大写需要大写能打开并且按键没坏
                if(TOP && !Hash[c + ' ']) putchar(c);
                else continue;  //如果想省略括号这个else必须写 没办法。。。。不然下一个else识别成这个
            else 
                if(!Hash[c])  putchar(c);      //没坏才能输出
        }
        puts("");   //补个格式
    }
    return 0;
}


B1038 统计同成绩学生 (20 分)

地址:B1038 统计同成绩学生 (20 分)

思路其实就是先统计,这里根本不用读入所有数据,直接统计就好了。


#include <cstdio>
#include <cstring>
int main(){
    int n;
    while(scanf("%d", &n) != EOF){
        int Hash[101],tmp,k;
        memset(Hash, 0 , sizeof(Hash)); //初始化  栈内存不给初始化 太难了。。。。
        while(n--){ //填充Hash表
            scanf("%d", &tmp);
            Hash[tmp]++;
        }
        scanf("%d", &k); 
        for(int i = 0;i < k; ++i){
            scanf("%d", &tmp);
            printf("%d", Hash[tmp]);
            if(i != k-1)    printf(" ");//格式控制
        }
        puts("");
    }
    return 0;
}

A1092 To Buy or Not to Buy (20 分)

地址:A1092 To Buy or Not to Buy (20 分)|B1039 到底买不买 (20 分)


其实思路还是很简单的,就是一个简单的hash表。需要注意一个点就是,不如边做事边计算长度,因为strlen这个库函数也是不断的往后读读到\0,所以如果用库函数 复杂度会成倍增长。


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int Hash[128];
char s1[1001], s2[1001];
int main(){
    while(cin.getline(s1,1001)){
        memset(Hash, 0 , sizeof(Hash));
        int count = 0;
        cin.getline(s2,1001);
        for(int i = 0;s2[i] ;++i)   ++Hash[s2[i]],++count;//设置hash表
        int count1 = count, count2 = 0;
        for(int i = 0;s1[i];++i){
            ++count2;
            if(Hash[s1[i]]) --Hash[s1[i]],--count;//查看是否满足要求
        }
        if(count != 0)  printf("No %d\n",count);    //还有未满足的珠子
        else printf("Yes %d\n",count2 - count1);    //全满足之间就是两串差
    }
    return 0;
}

B1042 字符统计 (20 分)

地址:B1042 字符统计 (20 分)


#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
char s[1009];
int Hash[128];  //Hash表
int main(){
    while(cin.getline(s,1009)){
        memset(Hash, 0, sizeof(Hash));
        char max = 0;
        for(int i = 0;s[i];++i){
            if(s[i] <= 'Z' && s[i] >= 'A')  s[i] += ' ';    //大写转换成小写
            else if(s[i] > 'z' || s[i] < 'a')   continue;   //不是字母 直接下一个
            ++Hash[s[i]];       //Hash统计
            if(Hash[s[i]] > Hash[max] || (Hash[s[i]] == Hash[max] && s[i] < max))  max = s[i];    //记录出现最多的字母
        }
        printf("%c %d\n",max, Hash[max]);
    }
    return 0;
}


B1043 输出PATest (20 分)

地址:B1043 输出PATest (20 分)

#include <cstdio>
#include <cstring>
int Hash[128];  //Hash表
const char ans[7] = "PATest";
int main(){
    int c,count = 0;
    while((c = getchar()) != EOF){
        char tmp = c;
        for(int i = 0; ans[i];++i)
            if(tmp == ans[i])   ++Hash[tmp], ++count;    //插入hash表
    }
    while(count){
        for(int i = 0; ans[i];++i)  //按序输出
            if(Hash[ans[i]])    --Hash[ans[i]],putchar(ans[i]), --count; 
    }
    puts("");
    return 0;
}


A1041 Be Unique (20 分)

地址:A1041 Be Unique (20 分)


看题目C…这玩意竟然一样 ,我惊了。


A1050 String Subtraction (20 分)

地址:A1050 String Subtraction (20 分)


看题目D…行吧,水题。。。。

B1005 继续(3n+1)猜想 (25 分)

地址:B1005 继续(3n+1)猜想 (25 分)

把3n+1猜想搬过来改改完事0.0


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int Hash[10000];//HASH表
int ans[101];   //记录所有数字
bool cmp(int a, int b ){return a > b;}
void kan(int n){
    Hash[n]++;
    if(Hash[n] > 1) return;
    if(n%2==1) kan((3*n+1)/2);
    if(n%2==0) kan(n/2);
}
int main(){
    int n;
    while(scanf("%d",&n) != EOF){
        memset(Hash, 0, sizeof(Hash));
        Hash[1] = 1;
        for(int i = 0;i < n;++i){
            scanf("%d",&ans[i]);
            kan(ans[i]);
        }
        int zhan[100],top = 0;
        for(int i = 0;i < n;++i)
            if(Hash[ans[i]] == 1){
                zhan[top++] = ans[i]; 
            }
        sort(zhan, zhan + top, cmp);
        for(int i = 0;i < top;++i){
            printf("%d",zhan[i]);
            if(i != top - 1) printf(" ");
        }
        puts("");
    }
    return 0;
}


A1048 Find Coins (25 分)

地址:A1048 Find Coins (25 分)


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int Hash[1000];
int main(){
    int n, m;
    while(scanf("%d %d", &n, &m) != EOF){
        memset(Hash, 0, sizeof(Hash));
        int min = 501;
        while(n--){
            int tmp;
            scanf("%d",&tmp);
            Hash[tmp]++;
            if(tmp + tmp == m){ //刚好一半  不能用m/2 这俩加和可能不能与m。。。。 因为是向下取整 你们懂的
                if(Hash[tmp] > 1)   min = tmp < min ? tmp: min;
            }
            else if(Hash[m - tmp])
                if(tmp <= m/2)  min = tmp < min ? tmp: min; //挑小的
                else min = (m - tmp) < min ? (m - tmp) :min;
        }
        if(min != 501)  printf("%d %d\n",min, m - min);
        else printf("No Solution\n");
    }
    return 0;
}


相关文章
|
12天前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
30 3
|
17天前
|
存储 算法 C#
C#哈希查找算法
C#哈希查找算法
|
18天前
|
算法 API 计算机视觉
人脸识别笔记(一):通过yuface调包(参数量54K更快更小更准的算法) 来实现人脸识别
本文介绍了YuNet系列人脸检测算法的优化和使用,包括YuNet-s和YuNet-n,以及通过yuface库和onnx在不同场景下实现人脸检测的方法。
27 1
|
18天前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
29 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
19天前
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
15 1
|
17天前
|
存储 算法
动态规划算法学习一:DP的重要知识点、矩阵连乘算法
这篇文章是关于动态规划算法中矩阵连乘问题的详解,包括问题描述、最优子结构、重叠子问题、递归方法、备忘录方法和动态规划算法设计的步骤。
70 0
|
18天前
|
数据可视化 搜索推荐 Python
Leecode 刷题笔记之可视化六大排序算法:冒泡、快速、归并、插入、选择、桶排序
这篇文章是关于LeetCode刷题笔记,主要介绍了六大排序算法(冒泡、快速、归并、插入、选择、桶排序)的Python实现及其可视化过程。
10 0
|
19天前
|
算法
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
❤️算法笔记❤️-(每日一刷-83、删除排序链表中的重复项)
28 0
|
19天前
|
算法
❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)
❤️算法笔记❤️-(每日一刷-26、删除有序数组的重复项)
23 0
|
7天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。