Posts 「算法刷题」牛客华为题库(一)
Post
Cancel

「算法刷题」牛客华为题库(一)

[TOC]

​ 华为机试题库共103道题目,其中入门级5道,简单级46道,中等级36道,较难级13道,困难级3道。

相关的API

>//将一个字符串中的字符全部转换为小写: for (int i = 0; i < str.length(); i++) { if ('A' <= str[i] && str[i] <= 'Z') str[i] += 32; } // 将一个字符转换为小写: char c=tolower(ch); // 在字符串末尾添加n个字符 str.append(n, '0'); // 根据索引获取字符串的子串 int len = str.size(); for (int i = 0; i < len; i += 8){ cout << str.substr(i, 8) << endl; } // 分割字符串 char s[]= "Golden~Global_View,disk*desk";//待分割的字符数组 const char *d = "~ ,*";// 分割字符集合 char *p; p = strtok(s,d);//s必须是char[] 类型 while(p) { printf("%s\n",p); p=strtok(NULL,d); } // 将n进制的字符串转换为十进制 #include <string> int stoi(str,x,n)//将 n 进制的str从索引x开始转化为十进制的整数 // 字符串转换为char [] char ch[20]; string s="123456"; strcpy(ch,s.c_str()); //计算x的y次幂 pow(x,y); //将数字常量转换为字符串 #include<string> int n; cin>>n; string s=to_string(n); //字符串的长度 s.length(); //将字符串逆序 #include<algorithm> reverse(s.begin(),s.end());//reverse函数的参数应该是迭代器? //获取字符串的子串 s.substr(3,5);//表示索引3开始的5个字符 //sort()函数 //sort默认按照字典序排序,即按照ASCII的顺序排序:数字,大写英文字母,小写英文字母 #include <algorithm>//sort位于这个头文件中 #include<vector> vector<int> arr; sort(arr.begin(),arr.end());//默认做升序排序

数字字符与数字的转换的两种方法:

第一种:

​ 用数字字符出减去’0’。例如:’1’-‘0’=1  (它俩是用ASCII码相减的。即49-48=1)

1+’0’=’1’

第二种:

​ 用数字字符出减去48。(48是‘0’的ASCII码)例如:’1’-48=1。

ASCII码的大小规则

常见ASCII码的大小规则:0~9<A~Z<a~z

0:48 A:65 a:97

1)数字比字母要小。如 “7”<“F”;

2)数字0比数字9要小,并按0到9顺序递增。如 “3”<“8” ;

3)字母A比字母Z要小,并按A到Z顺序递增。如“A”<“Z” ;

4)同个字母的大写字母比小写字母要小32。如“A”<“a” 。

几个常见字母的ASCII码大小: “A”为65;“a”为97;“0”为 48 [4] 。

在英语中,用128个符号编码便可以表示所有,但是用来表示其他语言,128个符号是不够的。

字符串流

1
2
3
#include <sstream>// 字符串流
string s;
stringstream ss(s);//将字符串转换为字符串流

字符串流是以内存中用户定义的字符串或字符数组为输入输出对象,也称为内存流 .

c++正则表达式

regex_match: match是全文匹配,即要求整个字符串符合匹配规则。

将逆序字符串的函数

1、直接调用函数

1
2
3
#include<algorithm>
#include<string>
reverse(s.begin(),s.end());

2、编写逆序函数

1
2
3
4
5
6
7
8
#include<string>
void reverseStr(string &str,int start,int end){
    int left=start;
    int right=end;
    while(left<right){
        swap(str[left++],str[right--]);
    }
}

按‘ 空格 ’分割字符串

并将分割出每个子字符串存到一个数组中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void split(string &str,vector<string> &arr){
    int left=0;
    int len=str.length();
    while(left<len){
        // left找到了第一个英文字符
        while(str[left]==' '&&left<len)left++;
        int right=left;
        // right找到单词后的第一个空格
        while(str[right]!=' '&&right<len)right++;
        //[left,right-1]
        arr.push_back(str.substr(left,right-left));
        //reverseStr(str,left,right-1);
        left=right;
    }
}

判断字符是否为大小写英文字母

1、直接使用现有的函数

1
2
3
#include<string>
string s;
isalpha(s);//返回值为false或true

2、

1
2
3
4
5
6
7
8
9
bool is_A(char c){
    if(c>='A'&&c<='Z')return true;
    return false;
}

bool is_a(char c){
    if(c>='a'&&c<='z')return true;
    return false;
}

动态数组:添加

vector arr;

arr.push_back();

c++的输出格式

1.转换说明符

%f 浮点数(包括float和double)

​ %c 字符 %d 有符号十进制整数

%i 有符号十进制整数(与%d相同) %u 无符号十进制整数

%s 字符串

2、格式字符: 用以指定输出项的数据类型和输出格式。

f格式:

%f:不指定宽度,整数部分全部输出并输出6位小数。 %m.nf:输出共占m列,其中有n位小数,如数值宽度小于m左端补空格。 %-m.nf:输出共占n列,其中有n位小数,如数值宽度小于m右端补空格。

sort函数

1
2
3
4
5
6
7
8
9
10
11
//sort默认按照字典序排序,即按照ASCII的顺序排序:数字,大写英文字母,小写英文字母
#include <algorithm>//sort位于这个头文件中
#include<vector>
vector<int> arr;
sort(arr.begin(),arr.end());//默认做升序排序

//降序排序
sort(arr.begin(),arr.end(),cmp);
bool cmp(int a,int b){
    return a>b;
}

双指针法删除数组中出现次数最少的元素

( 若出现次数最少的字符有多个,则把出现次数最少的字符都删除。 )

1
2
3
4
5
6
7
8
9
10
11
12
13
string s;
int left=0;
int right=0;
int n=s.length();
while(right<n){
   if(dict[s[right]]==min_q){//min_q是出现的最小次数
       right++;
   }
   else{
      s[left++]=s[right++]; 
   }
}
cout<<s.substr(0,left);

链表结点的定义

1
2
3
4
5
6
7
8
struct ListNode{
    int m_nKey;
    ListNode* m_pNext;
    ListNode(int val){
        m_nKey=val;
        m_pNext=NULL;
    }
};

创建链表

1
2
3
4
5
6
7
8
9
10
11
ListNode *myNode=new ListNode(0);
        ListNode *p=myNode;//遍历指针
        int temp=0;
        //创建链表
        while(n--){//n为链表节点个数

            cin>>temp;
            ListNode *newNode=new ListNode(temp);
            p->next=newNode;
            p=p->next;
        }

找链表中倒数第k个元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int k;
//头结点
ListNode *myCode=new ListNode(0);
//left,right都指向第一个节点(头节点的下一个结点)
ListNode *left=myCode->m_pNext;
ListNode *right=myCode->m_pNext;
//right先走k步
while(k--){
    right=right->m_pNext;
}
//left和right一起走,直到right指向NULL
while(right){
    left=left->m_pNext;
    right=right->m_pNexst;
}
cout<<left->m_nKey<<endl;

判断字符是否大小写字母、数字等的库函数

  1. isupper()判断一个字符是否是大写字母

  2. isalpha()判断一个字符是否是字母

  3. isblank()判断一个字符是否是空白符

  4. isdigit()判断一个字符是否是十进制数字

  5. islower()判断一个字符是否是小写字母

  6. isspace()判断一个字符是否是空白符

  7. tolower()将大写字母转换为小写字母

  8. toupper()将小写字母转换为大写字母

十进制转二进制

输入描述:

输入一个整数

输出描述:

计算整数二进制中1的个数

输入:

1
5

复制

输出:

1
2

复制

说明:

1
5的二进制表示是101,有2个1   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
using namespace std;

int main(void){
    int n;
    while(cin>>n){
        int  m=0;
        while(n){
            m+=n%2;
            n=n/2;
        }
        cout<<m<<endl;
    }
    
    
    return 0;
}

unordered_map查找某个元素是否存在的函数

1
2
3
4
unordered_map<string,int> mp;
string s;
mp.count(s)//返回值为0:不存在;1:存在。
mp.find(s)==mp.end();//mp中不存在s

按要求对哈希表排序

输入一个只包含小写英文字母和数字的字符串,按照不同字符统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASCII码由小到大排序输出。

方法一:使用自定义sort

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
#include<bits/stdc++.h>
using namespace std;
//函数参数加const,可以防止参数被改变
//函数参数加&,效率更高
bool cmp(const pair<char,int>& a,const pair<char,int>& b){
    if(a.second!=b.second){
        return a.second>b.second;
    }else{
        return a.first<b.first;
    }
}

int main(void){
    string s;
    getline(cin,s);
    unordered_map<char,int> mp;// k-v
    for(int i=0;i<s.size();i++){
        mp[s[i]]++;
    }
    vector<pair<char,int>> arr;
    for(auto iter=mp.begin();iter!=mp.end();++iter){
        arr.push_back(make_pair(iter->first, iter->second));
    }
    sort(arr.begin(),arr.end(),cmp);// 从大到小
    for(auto p:arr){
        cout<<p.first;
    }
    return 0;
}

方法二:优先级队列和仿函数(其实是个类)

仿函数的operator()是函数名。

priority_queue<pair<char,int>,vector<pair<char,int»,mycomp> que;的<>里的第一个是队列元素类型,第二个是把队列元素放到指定容器中进行排序。

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
#include <bits/stdc++.h>
using namespace std;

class mycomp{
public:
    bool operator()(const pair<char,int>& a,const pair<char,int>& b){
        if(a.second==b.second){
            return a.first>b.first;
        }
        else{
            return a.second<b.second;
        }
    }
};

int main(){
    // 获取输入
    string s;
    unordered_map<char,int> dict;
    priority_queue<pair<char,int>,vector<pair<char,int>>,mycomp> que;
    while(getline(cin, s)){
        for(char c:s) dict[c]++;//统计长字符串中的所有字符频率
        // 遍历
        for(auto p:dict){
            que.push(p);
        }
        // 输出
        while(!que.empty()){
            auto p=que.top();
            que.pop();
            cout<<p.first;
        }
        cout<<endl;
    }
}

十进制数字转为二进制字符串

1
2
3
4
5
6
7
8
int n;
    cin>>n;
    string s;
    //转为二进制
    while(n){
        s=to_string(n%2)+s;
        n/=2;
    }

合并两个有序数组

将两个整型数组按照升序合并,并且过滤掉重复数组元素。

输出时相邻两数之间没有空格。

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
 //合并两个有序数组
    string res;
    int i=0,j=0;
    unordered_set<int> set;//哈希集合,用来去重
    while(i<s1.size()&&j<s2.size()){
        if(s1[i]<=s2[j]){
            if(!set.count(s1[i])){//不重复的才添加
                set.insert(s1[i]);
                res+=to_string(s1[i]);
            }
            i++;
        }
        else if(s1[i]>s2[j]){//不重复的才添加
            if(!set.count(s2[j])){
                set.insert(s2[j]);
                res+=to_string(s2[j]);
            }
            j++;
        }
    }
    //数组s1没有比较完
    while(i<s1.size()){
        if(!set.count(s1[i])){
            set.insert(s1[i]);
            res+=to_string(s1[i]);
        }
        i++;
    }
    //数组s2没有比较完
    while(j<s2.size()){
        if(!set.count(s2[j])){
            set.insert(s2[j]);
            res+=to_string(s2[j]);
        }
        j++;
    }
    cout<<res;

判断是否为回文子串

1
2
3
4
5
6
7
8
9
//判断是否是回文子串
bool is_true(string &s){
    int left=0;
    int right=s.size()-1;
    while(left<=right){
        if(s[left++]!=s[right--])return false;
    }
    return true;
}

遍历所有的子串

1
2
3
4
5
6
7
8
//定义动态数组
    int len=s.size();
    for(int i=0;i<len;i++){
        for(int j=1;j<len-i+1;j++){
            string str=s.substr(i,j);
            //对字串进行处理
        }
    }
This post is licensed under CC BY 4.0 by the author.