秋招刷题笔记

刷题笔记

  • 体会
    • 哈希的使用
      • unordered_map以及map用法大全(其中有按value排序的)
      • 在一个unordered_map或者map中,如果找出key值最大或者最小的元素?
      • 在一个unordered_map或者map中,如果找出value值最大或者最小的元素?
      • 哈希表的输出顺序按key升序排序
      • 哈希表的输出顺序按key降序排序、按value升序或者降序排序
      • 输出按输入的顺序排序
    • vector的使用
      • 在一个数组或者向量中,找出最大值或最小值,返回对应的下标
      • 如何去除vector中重复的元素,只保留一个
      • vector向量中输出最后一个元素的方法,删除最后一个元素的方法
    • 字符串操作
      • 如何在字符串中间删除或者添加某个字符,保持其他字符不变?
    • 数学运算
      • 输出取小数点后几位
    • 各种注意事项
  • 杂记 ASCII字典 摩尔投票法 暴力 进制转换
      • 整数 自守数 平方的尾部等于自己 华牛 HJ99 easy 直接做
      • 字符串 给字符串中的数字左右加上* 华牛HJ96 easy 直接做
      • 字符串 s1的全部字符是否在s2中出现 华牛 HJ81 easy ASCII
      • 根据输入的年月日输出是第几天 牛华 HJ73 easy 直接做
      • 统计一个字符串中各种字符的个数 华牛 HJ40 easy 直接做 操作string单个字符的库函数
      • 计算 空汽水瓶换汽水 牛客华为 HJ22 easy 直接做
      • 字符串 根据手机按键转换字符串 牛客华为 HJ21 easy 直接做
      • 进制 16进制转10进制 牛客华为HJ5 easy 通过cin cout来格式化
      • 字符串 分割字符串,以8个为输出 牛客华为HJ4 easy 直接做
      • 字符串 计算某字符出现的次数(不区分大小写) 牛客华为HJ2 easy ASCII字典
      • 数组 数组中出现次数最多的数字 剑指 Offer 39改编 easy 摩尔投票
      • 字符串 无重复的最长子串 hot100 3 mid ASCII字典
      • 字符串 替换字符中的空格 剑指offer 5 easy 扩充数组
      • 字符串 找出字符串中第一次只出现一次的字符 剑指offer 50 easy ASCII字典
      • 链表 两个链表表示两个数,两数相加 HOT 100 2 mid 直接做
      • 链表 删除链表中某个val对应的节点 剑指offer 18 easy 直接做
      • 链表 合并两个排序的链表 剑指offer 25 easy 直接做
  • 字符串处理类题目
      • 坐标移动:字符串的分割,识别其中字母和数字 牛华 HJ17 mid
      • 字符子串substr查找,正则表达式 牛华HJ
  • 递归、动态规划、分治、贪心
      • 三个月大的兔子每个月生一个小兔子,统计每个月总数 牛华 HJ37 easy 记忆递归
      • 斐波拉契数列 剑指offer10-1 easy 记忆递归、dp、状态压缩
      • 数组 连续子数组的最大和 剑指Offer 42 easy
      • 字符串 最长回文子串 hot100 5 mid
  • 栈、队列
      • 对字符串中的所有单词进行倒排,字符串中包含其他符号 牛客华为机试 HJ31 easy string类型的栈
      • 字符串 将句子每个单词逆序输出 牛客华为机试 HJ13 easy string类型的栈
      • 字符串 整型数字转字符串然后反转输出 牛客华为 HJ11 easy to_string 栈
      • 链表 删除链表倒数第N个节点 hot 100 19 mid 栈
      • 链表 从头到尾打印链表 剑指offer 06 easy 栈
      • 链表 反转链表 剑指offer 24 easy 栈、双指针或者头插法
      • 字符串 有效的括号 hot 100 20 easy
      • 两个栈实现队列 剑指offer 09 easy
      • 包含min函数的栈 剑指offer 30 easy
  • 滑动窗口
      • 字符串 无重复的最长子串 hot100 3 mid hash_set
  • 排序和查找
      • 数组 合并两个无序数组,变为升序,删除重复元素只留一个 华牛HJ80 easy 库函数unique
      • 字符串 将一字符串从小到大进行排序 牛客华为机试 HJ14 easy string类型的sort函数
      • 数组 数组中出现次数超过一半的数字 剑指 Offer 39 easy 排序
      • 数组 输出数组中最小的k个数 剑指Offer 40 easy 排序
      • 数组 查找旋转数组中的最小数字 剑指offer 11 easy 二分查找
      • 数组 搜索旋转排序数组中的某个值 hot 100 33 mid 二分查找
      • 数组 在排序数组中查找元素的第一个和最后一个位置 hot 100 mid 二分
  • 哈希
      • 环形缓存加哈希记录 华牛 HJ9 hard
      • 一个int数从右到左提取不重复的数组成新数 华牛 HJ9 easy
      • 字符串 哈希表按value排序,考虑相等时的情况 华牛 HJ102 easy
      • 候选人票数的统计 华牛 HJ94 easy 按输入顺序输出哈希 map操作
      • 删除字符串中出现次数最少的字符 牛客华为 HJ23 easy 哈希找最小值
      • 计算字符串中含有的不同字符的个数 牛客华为 HJ10 easy 哈希set
      • 合并表记录 牛客华为 HJ8 easy 哈希map(有序哈希)哈希的遍历输出
      • 数组 两数之和 hot 100 01 easy
      • 数组 数组中重复的数字 剑指offer 03 easy
      • 数组 数组中出现次数超过三分之一的数字 剑指 Offer 39改编 easy
      • 链表 两个链表的第一个公共节点 剑指offer 52 easy hashmap
  • 工作指针
      • 输出链表倒数第k个节点 华牛 HJ51 easy ACM模式操作链表
      • 数组 盛水最多的容器 hot 100 11 mid
      • 数组 三数之和 hot 100 15 mid
      • 数组 调整数组顺序使奇数位于偶数前面 剑指 Offer 21 easy
      • 链表 两个链表的第一个公共节点 剑指offer 52 easy 有点类似快慢指针
  • 数学计算、位运算
      • 一个float数四舍五入取近似值 华牛 HJ7 easy
      • 一个整数的所有质数因子 华牛 HJ6 easy
      • int二进制数中连续的1的个数 华牛 HJ86 easy
      • 二进制中1的个数 剑指offer 15 easy

体会

哈希的使用

unordered_map以及map用法大全(其中有按value排序的)

https://blog.csdn.net/bitcarmanlee/article/details/124815289

在一个unordered_map或者map中,如果找出key值最大或者最小的元素?

auto j=min_element(hash.begin(),hash.end());//返回最小key对应的pair的迭代器
cout<<j->first<<endl;//输出最小的key值
cout<<j->second<<endl;//输出最小的key值对应的value

auto j=max_element(hash.begin(),hash.end());//返回最大key对应的pair的迭代器

在一个unordered_map或者map中,如果找出value值最大或者最小的元素?

/*找最大value对应的元素*/
bool cmp_value(const pair<char, int> left,const pair<char,int> right)
{
	return left.second > right.second;//大于符号,表示找最大的,pair根据实际情况换
}
auto j=min_element(hash.begin(),hash.end(),cmp_value);//返回最大value对应的pair的迭代器

/*找最小value对应的元素*/
bool cmp_value(const pair<char, int> left,const pair<char,int> right)
{
	return left.second <right.second;//小于符号,表示找最小的
}
auto j=min_element(hash.begin(),hash.end(),cmp_value);//返回最小key对应的pair的迭代器,注意最大最小都用min_element

哈希表的输出顺序按key升序排序

map自动按升序,如果key是字符,按ascii码,如果是字符串,按字符串大小规则

哈希表的输出顺序按key降序排序、按value升序或者降序排序

(1)**按key降序排序(**也可以直接用map,然后用栈反转)
将哈希表放进vector,再自己定义比较函数

bool mycompare_func(const pair<char, int> &a, const pair<char, int> &b) {
    /* return a.second
    if (a.firtt==b.first) return a.second<b.second;
    /* 这里表示谁的first更大,谁排前面,也就是整个vector按first的从大到小排列*/
    else return a.first>b.first;
}

 	unordered_map<char, int> m;//定义哈希表
 	...//自己按照需要填充哈希表
    vector<pair<char, int>> v(m.begin(), m.end());//将哈希表拷贝到vector
    sort(v.begin(), v.end(), mycompare_func);//按first从大到小排序排序
    for(auto it=v.begin(); it!=v.end(); it++) {//遍历输出vector
        cout<<it->first;
    }

(2)按second降序排序
将哈希表放进vector,再自己定义比较函数

bool mycompare_func(const pair<char, int> &a, const pair<char, int> &b) {
    /* return a.first
    if (a.second==b.second) return a.first<b.first;
    /* 这里表示谁的second更大,谁排前面,也就是整个vector按second的从大到小排列*/
    else return a.second>b.second;
}
 	unordered_map<char, int> m;//定义哈希表
 	...//自己按照需要填充哈希表
    vector<pair<char, int>> v(m.begin(), m.end());//将哈希表拷贝到vector
    sort(v.begin(), v.end(), mycompare_func);//按second从大到小排序排序
    for(auto it=v.begin(); it!=v.end(); it++) {//遍历输出vector
        cout<<it->first;
    }

(3)按second升序排序
将哈希表放进vector,再自己定义比较函数

bool mycompare_func(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;
}
 	unordered_map<char, int> m;//定义哈希表
 	...//自己按照需要填充哈希表
    vector<pair<char, int>> v(m.begin(), m.end());//将哈希表拷贝到vector
    sort(v.begin(), v.end(), mycompare_func);//按second从小到大排序排序
    for(auto it=v.begin(); it!=v.end(); it++) {//遍历输出vector
        cout<<it->first;
    }

输出按输入的顺序排序

在输入的时候额外创建一个vector来存放输入顺序,输出时按这个vector为索引输出哈希,具体看:
候选人票数的统计 华牛 HJ94 easy 按输入顺序输出哈希 map操作

vector的使用

在一个数组或者向量中,找出最大值或最小值,返回对应的下标

https://blog.csdn.net/shetougong/article/details/112627169

如何去除vector中重复的元素,只保留一个

答:https://blog.csdn.net/u010141928/article/details/78671603

vector向量中输出最后一个元素的方法,删除最后一个元素的方法

答:

//返回最后一个元素
 last=*(v.end()-1);//注意end是指向不存在的元素
 //删除最后一个元素
  v.pop_back();
  或者
  v.erase(v.end()-1);//end会自动更新

字符串操作

如何在字符串中间删除或者添加某个字符,保持其他字符不变?

https://blog.csdn.net/wang1997hi/article/details/78364755

数学运算

输出取小数点后几位

    double avg=0,sum=0;//注意两个都要是浮点型,不然会发生隐式的类型转换
    avg=sum/cnt_pos;
    cout<<fixed<<setprecision(1)<<avg<<endl;//括号里是几就保留几位
}

各种注意事项

如果是对某个链表进行操作,然后返回该链表,记得创建哑节点dummy
如果输出的结果是一个新的链表,一般需要用head tail,然后if(!head)else,防止最后多创建一个节点
递归一定要记得剪枝,用一个数组保存重复出现的值
return stack.top()时注意不要指向空指针
注意不能在类中定义vector,类内可以定义数组,在类外定义和初始化vector,类里面可以用
二分查找全是细节,一定要写熟练。第一个细节是如何中止二分(左边界小于等于右边界),第二个细节是每次查找如何调整左右边界(原则是新的左右边界一定要包含目标值,目标值可以在新边界的端点)
c++中字符数组用cout输出时,数组必须以’\0’结尾
ASCII字典第一个是空NULL,不是’ ',大写字母从65到90,小写字母从97到122,相差32。
栈 vector都可以存储string,sort函数可以对string进行排序。

杂记 ASCII字典 摩尔投票法 暴力 进制转换

整数 自守数 平方的尾部等于自己 华牛 HJ99 easy 直接做

#include
using namespace std;
int main(){
    int n,square=0,cnt=0;cin>>n;
    if(n==0){
        cout<<1<<endl;
        return 0;
    }
    while(n>0){
        square=pow(n,2);
        int tmp=10;
        while(square*10>=tmp){
            if(square%tmp==n){
                cnt++;
                break;
            }
            tmp=10*tmp;
        }
        n--;
    }
    cout<<cnt+1<<endl;
}

字符串 给字符串中的数字左右加上* 华牛HJ96 easy 直接做

#include
using namespace std;
int main() {
    string s,res;
    getline(cin,s);
    int len=s.size(),cnt=0;
    for(int i =0;i<len;i++){
        if(isdigit(s[i])&&cnt==0){
            cnt++;
            res+='*';
            res+=s[i];
        }
        else if(!isdigit(s[i])&&cnt>0){
            res+='*';
            res+=s[i];
            cnt=0;
        }
        else 
            res+=s[i];
    }
    if(isdigit(s[len-1]))
        res+='*';
    cout<<res<<endl;
    return 0;
}

字符串 s1的全部字符是否在s2中出现 华牛 HJ81 easy ASCII

#include
using namespace std;
int main(){
    int ascii[26]={0};
    string s,t;
    getline(cin,s);
    getline(cin,t);
    int lent=t.size();
    int lens=s.size();
    for(int i=0;i<lent;i++){
        ascii[t[i]-'a']++;
    }
    for(int i=0;i<lens;i++){
        if(ascii[s[i]-'a']>0)
            continue;
        else{
            cout<<"false"<<endl;
            return 0;
        }
    }
    cout<<"true"<<endl;
    return 0;
}

根据输入的年月日输出是第几天 牛华 HJ73 easy 直接做

#include 
using namespace std;
int main(){
    int year,month,day,res=0;
    cin>>year>>month>>day;
    int list[] ={31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
    if (month == 1)
        res = day;
    else if((year%4==0&&year%100!=0)||(year%400==0))
        res= list[month - 2] + day;
    else
         res = list[month - 2] + day - 1;
    cout<<res<<endl;
    return 0;
}

统计一个字符串中各种字符的个数 华牛 HJ40 easy 直接做 操作string单个字符的库函数

#include
using namespace std;
int main(){
    string s;
    getline(cin,s);
    int len=s.size(),cnt1=0,cnt2=0,cnt3=0,cnt4=0;
    for(int i=0;i<len;i++){
        if(isalpha(s[i]))
            cnt1++;
        else if(s[i]==' ')
            cnt2++;
        else if(isdigit(s[i]))
            cnt3++;
        else
            cnt4++;
    }
    cout<<cnt1<<endl<<cnt2<<endl<<cnt3<<endl<<cnt4<<endl;
    return 0;
}

计算 空汽水瓶换汽水 牛客华为 HJ22 easy 直接做

#include
using namespace std;
int main() {
    int a,more=0,res=0;
    while(cin>>a&&a!=0){
        while(a/3!=0){
            res+=a/3;//这次换的汽水
            more+=a%3;//不足三个的汽水
            a=a/3+ more;//喝完空出来的汽水加上之前不足的  
            more=0;//把不足的清0
        }
        more+=a%3;
        if(more==2){//只有不足的为2时,才能借一个空气瓶
            res++;
        }
        cout<<res<<endl;
        res=0;
        more=0;
    }
    return 0;
}

字符串 根据手机按键转换字符串 牛客华为 HJ21 easy 直接做

#include
#include
using namespace std;
int main(){
    string s;
    getline(cin,s);
    int len=s.size();
    char res[len+1];
    for(int i=0;i<len;i++){
        if(s[i]>=97&&s[i]<=99){//小写字母abc
            res[i]='2';
        }
        else if(s[i]>=100&&s[i]<=102){
             res[i]='3';
        } 
        else if(s[i]>=103&&s[i]<=105){
             res[i]='4';
        }
        else if(s[i]>=106&&s[i]<=108){
             res[i]='5';
        }
        else if(s[i]>=109&&s[i]<=111){
             res[i]='6';
        }
        else if(s[i]>=112&&s[i]<=115){
             res[i]='7';
        }
        else if(s[i]>=116&&s[i]<=118){
             res[i]='8';
        }
        else if(s[i]>=119&&s[i]<=122){
             res[i]='9';
        }
        else if(s[i]>=65&&s[i]<=89){//大写字母
             res[i]=s[i]+33;
        }
        else if(s[i]==90){//大写字母Z
            res[i]='a';
        }
        else{
            res[i]=s[i];
        }
    }
    res[len]='\0';
    cout<<res<<endl;
    return 0;
}

进制 16进制转10进制 牛客华为HJ5 easy 通过cin cout来格式化

题解:cin和cout有自己的格式化操作,在输入输出前加hex,表示后续这个是十六进制的数,在输入输出前加dec,表示后续这个是十进制的数,我们可以利用这个原理让输出的变成十六进制数,输出成十进制数。

#include
using namespace std;
 
int main(){
    int res = 0;
    while(cin >> hex >> res)  //hex表示读入十六进制数
        cout << dec << res << endl; //dec表示输出十进制数
    return 0;
}

字符串 分割字符串,以8个为输出 牛客华为HJ4 easy 直接做

题解:注意字符数组需要多创建一位,存放\0。

#include 
#include 
#include 
using namespace std;
int main() {
    string s;
    getline(cin,s);
    int len=s.size(),i=0,cnt=0;
    vector<char>arr;
    for(int i=0;i<len;i++){
        if(s[i]!=' '){
            arr.push_back(s[i]);
        }
    }
    int newlen=arr.size();
    char ans[9];
    for(i=0;i<newlen;i++){
        if(i%8==7){
            ans[i%8]=arr[i];
            ans[8]='\0';
            cout<<ans<<endl;
            cnt++;
        }
        ans[i%8]=arr[i];
    } 
    int more=newlen-8*cnt;
    if(more!=0){
        for(i=more;i<8;i++){
        ans[i]='0';
        }
    ans[8]='\0';
    cout<<ans<<endl; 
    }
    return 0;
}

字符串 计算某字符出现的次数(不区分大小写) 牛客华为HJ2 easy ASCII字典

题解:注意不区分大小写如何处理。首先ASCII字典第一个是空NULL,不是’ ',大写字母从65到90,小写字母从97到122,相差32。

#include
#include
using namespace std;
int main(){
    string s;
    getline(cin,s);
    char target;
    cin>>target;
    int arr[128]={0};
    int len=s.size(),ans=0;
    for(int i=0;i<len;i++){
        arr[s[i]-NULL]++;
    }   
    if((target-NULL)>=65&&(target-NULL)<=90){
        ans=arr[target-NULL]+arr[target-NULL+32];
    }
    else if((target-NULL)>=97&&(target-NULL)<=122){
        ans=arr[target-NULL]+arr[target-NULL-32];
    }
    else{
        ans=arr[target-NULL];
    }
    cout<<ans<<endl;
    return 0;
}

数组 数组中出现次数最多的数字 剑指 Offer 39改编 easy 摩尔投票

题解: 原题是超过一半,这样可以排序然后取中值,如果改成三分之一,可以用hash记录每个数组项目出现的次数,如果改成出现次数最多的数字,排序和哈希都不太好弄,可以用摩尔投票法,或者叫极限一换一

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int res = 0, count = 0;
        for(int i = 0; i < nums.size(); i++){
            if(count == 0){
                res = nums[i];
                count++;
            }
            else
                res==nums[i] ? count++:count--;
        }
        return res;
    }
};

字符串 无重复的最长子串 hot100 3 mid ASCII字典

题解: 时间100%

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
vector<int> m(128,0);//这个容器为了存当遇到相同的字符(假设是a)时i应该变成的值,即前面那个a的下一个字符
int ans=0; //最终的子串长度
int i=0;
for(int j=0;j<s.size();j++){
    i=max(i,m[s[j]]);//如果遇到了相同的字符(假设为a),此时m[s[j]]会又去到同样的存储单元m[a的ASCII码值],因为之前遇到a时已经将这个位置的值改成前面那个a的下一个位置了,所以m[s[j]]大于i,将i更新
    m[s[j]]=j+1;//更新这个位置的值,当下次再遇到该字母时,将i调整到该字母下一个位置的地方
    ans=max(ans,j-i+1);//更新最终结果值,即没相同字母的子串的字符个数
}
return ans;
    }
};

字符串 替换字符中的空格 剑指offer 5 easy 扩充数组

题解1: 其实可以直接用库函数

return s.replace(" ","%20");

题解2: 数空格个数,新建一个数组

class Solution {
public:
    string replaceSpace(string s) {
        int i=0,j=0,cnt=0,len=s.size(),newlen=0;
        while(i<len){
            if(s[i]==' ')
                cnt++;
                i++;
        }
        newlen=len+2*cnt;
        char* newstring=new char[newlen+1];
        i=0;
        while(i<len){
            if(s[i]==' '){
                newstring[j]='%';
                newstring[j+1]='2';
                newstring[j+2]='0';
                j+=3;
                i++;
            }
            else{
                newstring[j]=s[i];
                j++;
                i++;
            }
        }
        newstring[newlen]='\0';
        return newstring;
    }
};

字符串 找出字符串中第一次只出现一次的字符 剑指offer 50 easy ASCII字典

题解: 这种方法扩展开,不管想找出现几次的都行,这一类题都可以搞定

class Solution {
public:
    char firstUniqChar(string s) {
            vector<int> m(26,0);
            int i=0,len=s.size();
            for(i=0;i<len;i++){
                m[s[i]-'a']++;
            }
            for(i=0;i<len;i++){
                if(m[s[i]-'a']==1)
                return s[i];
            }
            return ' ';
    }
};

链表 两个链表表示两个数,两数相加 HOT 100 2 mid 直接做

题解1: 运行报错,说访问空指针,不明白为什么

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
       int more=0,n1=0,n2=0;
       ListNode * ans= new ListNode();
       ListNode * cur= ans;
       while(l1||l2){
           n1=l1? l1->val:0;
           n2=l2? l2->val:0;
           cur->val=(n1+n2+more)%10;
           more=(n1+n2+more)/10;
           if(l1->next!=nullptr||l2->next!=nullptr){//就是这里报错,这里加条件是为了防止创建多余的节点
                cur->next=new ListNode();
                cur=cur->next;
           }
           if(l1){
               l1=l1->next;
           }
           if(l2){
               l2=l2->next;
           }
       }
       if(more>1){
            cur->next=new ListNode(more);   
       }
       return ans;
    }
};

题解2: 将节点创建整体往后拉一个序号,注意这种方法,输出的结果需要创建一个新链表时,这样非常有用

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *head = nullptr, *tail = nullptr;//用于存放结果的链表的头尾指针
        int carry = 0;//存放进位的数
        while (l1 || l2) {
            int n1 = l1 ? l1->val: 0;
            int n2 = l2 ? l2->val: 0;
            int sum = n1 + n2 + carry;
            if (!head) {
                head = tail = new ListNode(sum % 10);
            } else {
                tail->next = new ListNode(sum % 10);
                tail = tail->next;
            }
            carry = sum / 10;
            if (l1) {
                l1 = l1->next;
            }
            if (l2) {
                l2 = l2->next;
            }
        }
        if (carry > 0) {
            tail->next = new ListNode(carry);
        }
        return head;
    }
};

链表 删除链表中某个val对应的节点 剑指offer 18 easy 直接做

class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
            ListNode* dummy=new ListNode();
            dummy->next=head;
            ListNode* cur=dummy;
            while(cur->next){//这里一定得cur->next
                if(cur->next->val==val){
                    cur->next=cur->next->next;
                    return dummy->next;//这里一定得返回
                }
                else{
                    cur=cur->next;
                }
            }
            return dummy->next;
    }
};

链表 合并两个排序的链表 剑指offer 25 easy 直接做

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
         ListNode* p1=l1,*p2=l2,*dummy=new ListNode();
         ListNode* cur=dummy;
         if(!p1||!p2){
             return p1? p1:p2;
         }
         while(p1&&p2){
             if(p1->val<p2->val){
                 cur->next=p1;//这里必须用next
                 p1=p1->next;
             }
            else{
                 cur->next=p2;
                 p2=p2->next;
             }
             cur=cur->next;
         }
         cur->next=p1? p1:p2;
         return dummy->next;
    }
};

字符串处理类题目

坐标移动:字符串的分割,识别其中字母和数字 牛华 HJ17 mid

#include
using namespace std;
int main(){
    char input; int x=0,y=0;
    string s; vector<string> v;
    while(cin>>input){
        if(input==';'){
            v.emplace_back(s);
            s.clear();
        }
        else 
            s+=input;
    }
    int len=v.size();
    for(int i=0;i<len;i++){
        if(v[i][0]=='A'||v[i][0]=='W'||v[i][0]=='S'||v[i][0]=='D'){
            if(v[i].size()==3&&isdigit(v[i][1])&&isdigit(v[i][2])){
                int tmp1=(int)(v[i][1]-'0');
                int tmp2=(int)(v[i][2]-'0');
                int tmp=10*tmp1+tmp2;
                if(v[i][0]=='A')
                    x-=tmp;
                if(v[i][0]=='W')
                    y+=tmp;
                if(v[i][0]=='S')
                    y-=tmp;
                if(v[i][0]=='D')
                    x+=tmp;
            }
            if(v[i].size()==2&&isdigit(v[i][1])){
                int tmp=(int)(v[i][1]-'0');
                if(v[i][0]=='A')
                    x-=tmp;
                if(v[i][0]=='W')
                    y+=tmp;
                if(v[i][0]=='S')
                    y-=tmp;
                if(v[i][0]=='D')
                    x+=tmp;
            }
        }
    }
    cout<<x<<","<<y<<endl;
}

字符子串substr查找,正则表达式 牛华HJ

解法一:暴力解法,用到字符字串substr

#include
using namespace std;
int main(){
    string s;
    while(cin >> s){
        if(s.length() <= 8){ //长度不超过不可行
            cout << "NG" << endl;
            continue;
        }
        int flag[4] = {0};
        for(int i  = 0; i < s.length(); i++){
            if(s[i] >= 'A' && s[i] <= 'Z') //大写字母
                flag[0] = 1;
            else if(s[i] >= 'a' && s[i] <= 'z') //小写字母
                flag[1] = 1;
            else if(s[i] >= '0' && s[i] <= '9') //数字
                flag[2] = 1;
            else  //其他符号
                flag[3] = 1;
        }
        if(flag[0] + flag[1] + flag[2] + flag[3] < 3){ //符号少于三种
            cout << "NG" << endl;
            continue;
        }
        bool repute = false; //记录重复子串
        for(int i = 0; i <= s.length() - 6; i++) //遍历检查是否有长度为3的相同的字串
            for(int j = i + 3; j < s.length()-3; j++)
                if(s.substr(i, 3) == s.substr(j, 3)){
                    repute = true;
                    break;
                }
        if(repute) //有重复
            cout << "NG" << endl;
        else
            cout << "OK" << endl;
    }
    return 0;
}

递归、动态规划、分治、贪心

三个月大的兔子每个月生一个小兔子,统计每个月总数 牛华 HJ37 easy 记忆递归

#include
using namespace std;
int temp[31]={0};
int tuzi(int n){
    if(temp[n])
        return temp[n];
    if(n<=2)
        return 1;
    else {
        temp[n]=tuzi(n-1)+tuzi(n-2);
        return temp[n];
    }
    return -1;
}
int main(){
    int n;
    cin>>n;
    int res=tuzi(n);
    cout<<res;
    return 0;
}

斐波拉契数列 剑指offer10-1 easy 记忆递归、dp、状态压缩

题解1:记忆递归,纯递归会超时

vector<int> arr(101);
class Solution {
public:
    int fib(int n) {
        if(n==0){
            return 0;
        }
        else if(n==1){
            return 1;
        }
        else{
            if(arr[n]!=0){
                return arr[n];
            }
            else{
                arr[n]=(fib(n-1)+fib(n-2))%1000000007;
                return arr[n];
            }
        }
        return -1;
    }
};

题解2:动态规划

class Solution {
public:
int f[3];
    int fib(int n) {
       f[0]=0;f[1]=1;
       for(int i=2;i<=n;i++){
           f[i%3]=(f[(i-1)%3]+f[(i-2)%3])%1000000007;
       }
       return f[n%3];
    }
};

数组 连续子数组的最大和 剑指Offer 42 easy

题解1: 动态规划或者分治法,待刷

字符串 最长回文子串 hot100 5 mid

题解1: 动态规划,待刷

栈、队列

对字符串中的所有单词进行倒排,字符串中包含其他符号 牛客华为机试 HJ31 easy string类型的栈

题解:这道题跟HJ13基本一样

#include
using namespace std;
int main(){
    string s,temp;
    stack<string>stk;
    getline(cin,s);
    int cnt=0;
    int len=s.size();
    for(int i=0;i<len;i++){
        if(islower(s[i])||isupper(s[i])){
            temp+=s[i];
        }
        else if(!temp.empty()){
            stk.push(temp);
            temp.clear();
        }
    }
    if(!temp.empty())
        stk.push(temp);
    while(!stk.empty()){
        cout<<stk.top()<<' ';
        stk.pop();
    }
    return 0;
}

字符串 将句子每个单词逆序输出 牛客华为机试 HJ13 easy string类型的栈

题解: 一是栈可以放string,而是string不能像数组那样每个s[i]单独赋值

#include 
using namespace std;
int main(){
    string s;
    getline(cin,s);
    stack<string>stk;
    string res;
    int i=0,len=s.size();
    for(i=0;i<len;i++){
        if(s[i]==' '){
            stk.push(res);
            res.clear();
        }
        else if(i==len-1){
            res+=s[i];//这里原本是res[j]=s[i],这样不可以,res+=s[i]是string加字符字面值,这个用法在C++primer 80
            stk.push(res);
            res.clear();
        }
        else{
            res+=s[i];
        }
    }    
    while(!stk.empty()){
        cout<<stk.top()<<' ';
        stk.pop();
    }
    return 0;
}

字符串 整型数字转字符串然后反转输出 牛客华为 HJ11 easy to_string 栈

#include
using namespace std;
int main() {
    int a;
    cin>>a;
    stack<char> stk;
    string s;
    s=to_string(a);
    int len=s.size();
    for(int i=0;i<len;i++){
        stk.push(s[i]);
    }
    int j=0;
    while(!stk.empty()){
        s[j]=stk.top();
        stk.pop();
        j++;
    }
    cout<<s<<endl;
    return 0;
}

链表 删除链表倒数第N个节点 hot 100 19 mid 栈

题解:还有一种快慢指针的手法,ACM模式,多组输入

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);//创建哑节点
        stack<ListNode*> stk;//创建一个存放ListNode*的栈
        ListNode* cur = dummy;
        while (cur) //将包括哑节点在内的所有节点都压入栈
        {
            stk.push(cur);
            cur = cur->next;
        }
        for (int i = 0; i < n; ++i) //弹出后n个节点,注意C++中POP操作并不返回值
        {
            stk.pop();
        }
        ListNode* prev = stk.top();
        prev->next = prev->next->next;
        ListNode* ans = dummy->next;
        //这里换成ListNode* ans = head;会报错,不知道为什么,链表操作都按这个固定范式来就行
        delete dummy;
        return ans;
    }
};

链表 从头到尾打印链表 剑指offer 06 easy 栈

class Solution {
public:
    vector<int> reversePrint(ListNode* head) {
        stack<int>stk;
        ListNode* cur=head;
        vector<int>ans;
        int temp=0;
        while(cur){
            stk.push(cur->val);
            cur=cur->next;
        }
        while(!stk.empty()){
            temp=stk.top();
            stk.pop();
            ans.push_back(temp);
        }
        return ans;
    }
};

链表 反转链表 剑指offer 24 easy 栈、双指针或者头插法

题解1: 栈,栈中存放指针,而不是数据,这样不管数据是啥都可以操作

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
            if(head==nullptr)
                return head;
            ListNode* cur=head;
            ListNode* temp,*res;
            int cnt=0;
            stack<ListNode *>stk;
            while(cur){
                stk.push(cur);
                cur=cur->next;
            }
            while(!stk.empty()){
                temp=stk.top();
                if(cnt==0){
                    cnt++;
                    res=stk.top();
                }
                stk.pop();
                if(!stk.empty())
                    temp->next=stk.top();
            }
            temp->next=nullptr;
            return res;
    }
};

题解2: 双指针,这种方法是在原链表上修改的,如果题目要求不能引入额外空间,就只能这种方法

struct ListNode* reverseList(struct ListNode* head) {
    struct ListNode* prev = NULL;
    struct ListNode* next;
    while (head) {
        next= head->next;
        head->next = prev;
        prev = head;
        head = next;
    }
    return prev;
}

题解3: 头插法建立一个新链表

struct ListNode* reverseList(struct ListNode* head) {
    struct ListNode* new = (struct ListNode*)malloc(sizeof(struct ListNode));
    new->next=NULL;
    while (head) {
        struct ListNode* p = (struct ListNode*)malloc(sizeof(struct ListNode));
        p->val=head->val;
        p->next=new->next;
        new->next=p; 
        head=head->next;
    }
    return new->next;
}

字符串 有效的括号 hot 100 20 easy

class Solution {
public:
    bool isValid(string s) {
        stack<char>stk;
        int i=0,len=s.size(),left=0,right=0;
        if(len%2==1)
        return false;
        while(i<len){
            if(s[i]=='('||(s[i]=='{'||(s[i]=='[')))
            {
                stk.push(s[i]);
                left++;
            }
            else{
                right++;
                if(stk.empty())
                return false;
                else if(s[i]==')'&&stk.top()=='(')
                    stk.pop();
                else if(s[i]=='}'&&stk.top()=='{')
                    stk.pop();
                else if(s[i]==']'&&stk.top()=='[')
                    stk.pop();
                else
                 return false;
            }
            i++;
        }
        if(left!=right)
        return false;
        return true;
    }
};

两个栈实现队列 剑指offer 09 easy

class CQueue {
private: 
    stack<int>instack,outstack;
    int temp; 
public:
    CQueue() {
    } 
    void appendTail(int value) {
        instack.push(value);
    } 
    int deleteHead() {
        if(outstack.empty()){
            if(instack.empty()){
                return -1;
            }
            while(!instack.empty()){
                outstack.push(instack.top());
                instack.pop();
            }
            temp=outstack.top();
            outstack.pop();
            return temp;
        }
        else{
            temp=outstack.top();
            outstack.pop();
            return temp;
        }
        return -1;
    }
};

包含min函数的栈 剑指offer 30 easy

class MinStack {
private:
    stack<int>instk,minstk;
    int curmin=0;
public:
    MinStack() {
         minstk.push(INT_MAX);//这句话必须加,不然下面return minstk.top()会报错
         //初始化最小栈的栈顶元素为最大值为了防止top访问空指针报错
         //为什么只加minstk不加instk呢,是因为top函数之前肯定有push函数,push会填充instk,不用担心instk访问空指针
         //而调用min函数时,不一定之前调用了push,minstk不一定有数据
    }   
    void push(int x) {
        if(instk.empty()){
            curmin=x;
            instk.push(x);
            minstk.push(curmin);
        }
        else if(x<=curmin){
            curmin=x;
            instk.push(x);
            minstk.push(curmin);
        }
        else{
            instk.push(x);
        }
    }   
    void pop() {
        if(instk.top()==curmin){
            instk.pop();
            minstk.pop();
            curmin=minstk.top();
        }
        else{
            instk.pop();
        }
    }   
    int top() {
            return instk.top();
    }
    int min() {
            return minstk.top();
    }
};

滑动窗口

字符串 无重复的最长子串 hot100 3 mid hash_set

题解1: hash map

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size()==0)
         return 0;
            unordered_map<char,int> hash;
            int head=0,tail=0,ans=0,len=s.size();
            while(tail<len){
                hash[s[tail]]++;
                if(hash[s[tail]]==2){
                    hash[s[tail]]--;
                    hash[s[head]]--;
                    ans=max((tail-head),ans); 
                    head++;  
                }
                else{
                    tail++;
                    ans=max((tail-head),ans);//这里别忘了
                }
            }
            return ans;
    }
};

题解2: hash set

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size() == 0) return 0;
        unordered_set<char> hash;
        int head=0,tail=0,ans=0,len=s.size();
        while(tail<len){
            if(hash.find(s[tail]) != hash.end()){
                hash.erase(s[head]);
                ans = max(ans,tail-head);
                head ++;
            }
            else{
                hash.insert(s[tail]);
                tail++;
                ans = max(ans,tail-head);
            }
    }
        return ans;      
    }
};

排序和查找

数组 合并两个无序数组,变为升序,删除重复元素只留一个 华牛HJ80 easy 库函数unique

#include
using namespace std;
int main() {
    int size1,size2,a,i=0;
    vector<int> vec;
    cin>>size1;
    while(i<size1){
        cin>>a;
        vec.emplace_back(a);
        i++;
    }
    i=0;
    cin>>size2;
    while(i<size2){
        cin>>a;
        vec.emplace_back(a);
        i++;
    }
    sort(vec.begin(),vec.end());
    vec.erase(unique(vec.begin(),vec.end()),vec.end());
    int len=vec.size();
    for(i=0;i<len;i++){
        cout<<vec[i];
    }
    return 0;
}

字符串 将一字符串从小到大进行排序 牛客华为机试 HJ14 easy string类型的sort函数

题解: 注意sort函数也可以对string进行排序。

#include 
#include 
#include 
using namespace std;
int main(){
    vector<string> vec;
    int n;
    cin>>n;
    string s;
    while(cin>>s){
        vec.emplace_back(s);
    }
    sort(vec.begin(),vec.end());
    int len=vec.size();
    for(int i=0;i<len;i++){
        cout<<vec[i]<<endl;
    }
}

数组 数组中出现次数超过一半的数字 剑指 Offer 39 easy 排序

题解: 直接快排,注意快排的函数语法,这道题也可以用哈希和摩尔投票法

class Solution {
public:
    int majorityElement(vector<int>& nums) {
       sort(nums.begin(),nums.end());
       return nums[nums.size()/2];
    }
};

数组 输出数组中最小的k个数 剑指Offer 40 easy 排序

题解: 快排,再循环输出

class Solution {
public:
    vector<int> getLeastNumbers(vector<int>& arr, int k) {
            sort(arr.begin(),arr.end());
            vector<int> ans;
            for(int i=0;i<k;i++){
                ans.push_back(arr[i]);
            }
            return ans;
    }
};

数组 查找旋转数组中的最小数字 剑指offer 11 easy 二分查找

class Solution {
public:
    int minArray(vector<int>& numbers) {
        int left=0,right=numbers.size()-1,mid=0;
        while(left<right){
            mid=left+(right-left)/2;
            if(numbers[mid]<numbers[right]){
                right=mid;
            }
            else if(numbers[mid]>numbers[right]){
                left=mid+1;
            }
            else{
                right--;
            }
        }
        return numbers[left];
    }
};

数组 搜索旋转排序数组中的某个值 hot 100 33 mid 二分查找

题解: 将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。
此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环.

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0,len=nums.size(),mid=0;
        int right=len-1;
        if(len==0){
            return -1;
        }
        if(len==1){
            return nums[0]==target? 0:-1;
        }
        while(left<=right){
            mid=left+(right-left)/2;
            if(nums[mid]==target){//这个放到最先来判断,节省时间
                return mid;
            }
            if(nums[left]<=nums[mid]){//左边是有序的
                if(target>=nums[left]&&target<nums[mid]){//目标值在左边有序数组中
                    right=mid-1;//调整右边界
                }
                else{
                    left=mid+1;//目标值不在左边有序数组中,在右边无序数组,调整左边界
                }
            }
            else{//右边是有序的
                if(target>nums[mid]&&target<=nums[right]){
                    left=mid+1;
                }
                else{
                    right=mid-1;
                }               
            }
        }
        return -1;
    }
};

数组 在排序数组中查找元素的第一个和最后一个位置 hot 100 mid 二分

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int len=nums.size();
        int left=0,right=len-1,mid=0,i=0;
        if(len==0){
            return {-1,-1};
        }
        if(len==1){
            if(nums[0]==target)
                return{0,0};
            else
                return{-1,-1};
        }
        while(left<=right){
            mid=left+(right-left)/2;
            if(nums[mid]==target){
                break;
            }
            if(nums[mid]<target){
                left=mid+1;
            }
            else{
                right=mid-1;
            }
        }
        if(nums[mid]!=target){
            return {-1,-1};
        }
        while((mid-i)>=0&&nums[mid-i]==target){
            i++;
        }
        left=mid-i+1;
        i=0;
        while((mid+i)<len&&nums[mid+i]==target){
            i++;
        }
        right=mid+i-1;
        return{left,right};
    }
};

哈希

环形缓存加哈希记录 华牛 HJ9 hard

#include
using namespace std;
string getfilename(string filepath){ //题取文件名
    string res = "";
    for(int i = filepath.length() - 1; i >= 0; i--){ //逆向查找到第一个斜杠
        if(filepath[i] ==  '\\')
            break;
        res = filepath[i] + res; //将字符加到字符串前面
    }
    if(res.length() > 16) //长度大于16的时候,截取后16位
        res = res.substr(res.length() - 16, 16);
    return  res;
}
int main(){
    string filepath, num; //把路径和行号都当成字符串
    unordered_map<string, int> mp;
    vector<string> res(8, "");
    int index = 0; //记录下标
    while(cin >> filepath >> num){
        string file = getfilename(filepath);
        string key = file + " " + num;
        if(mp.find(key) == mp.end()){ //没有出现过,需要添加到哈希表中
            mp[key] = 1;
            res[index] = key;
            index = (index + 1) % 8; //循环记录
        }else
            mp[key]++; //遇到相同的错误,计数增加
    }
    for(int i = 0; i < 8; i++){
        if(res[index] != "") //只输出有记录的,防止不足8个
            cout << res[index] << " " << mp[res[index]] << endl;
        index = (index + 1) % 8;
    }
    return 0;
}

一个int数从右到左提取不重复的数组成新数 华牛 HJ9 easy

#include
using namespace std;
bool mycompare_func(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(){
    int n,i=1; cin>>n;
    unordered_map<int, int> hash;
    while(n){
        if(hash.find(n%10)==hash.end())
            hash[n%10]=i;
        i++;
        n=n/10;
    }
    vector<pair<int, int>> v(hash.begin(), hash.end());//将哈希表拷贝到vector
    sort(v.begin(), v.end(), mycompare_func);//按second从小到大排序排序
    int len=v.size()-1,ans=0;
    for(auto it=v.begin(); it!=v.end(); it++) {//遍历输出vector
        ans+=it->first*pow(10,len);
        len-=1;
    }
    cout<<ans<<endl;
    return 0;
}

字符串 哈希表按value排序,考虑相等时的情况 华牛 HJ102 easy

#include
using namespace std;
bool mycompare_func(const pair<char, int> &a, const pair<char, int> &b) {
    /*return a.first
    if (a.second==b.second) return a.first<b.first;
    else return a.second>b.second;
}
int main(){
    string s;getline(cin,s);
    unordered_map<char, int> m;
    int len=s.size();
    for(int i=0;i<len;i++){
        m[s[i]]++;
    }
    vector<pair<char, int>> v(m.begin(), m.end());
    sort(v.begin(), v.end(), mycompare_func);
    for(auto it=v.begin(); it!=v.end(); it++) {
        cout<<it->first;
    }
    return 0;
}

候选人票数的统计 华牛 HJ94 easy 按输入顺序输出哈希 map操作

#include
using namespace std;
int main() {
    int n_wait,i=0;cin>>n_wait;
    map<string,int> map_wait;
    string s_wait;
    vector<string> vec_wait;
    while(i<n_wait){
        cin>>s_wait;
        vec_wait.emplace_back(s_wait);
        map_wait.insert(make_pair(s_wait,0));
        i++;
    }
    map_wait.insert(make_pair("Invalid",0));
    int n_vote;cin>>n_vote;i=0;
    vector<string> vec_votes;
    string s_vote;
    while(i<n_vote){
        cin>>s_vote;
        vec_votes.emplace_back(s_vote);
        i++;
    }
    int len=vec_votes.size();
    for(int i=0;i<len;i++){
        auto it=map_wait.find(vec_votes[i]);
        if(it!=map_wait.end()){
            it->second++;
        }
        else{
            map_wait["Invalid"]++;
        }
    }
    for(int i=0;i<n_wait;i++){//注意这里,完成了按照输入顺序输出哈希
        cout<<vec_wait[i]<<" : "<<map_wait[vec_wait[i]]<<endl;
    }
    cout<<"Invalid"<<" : "<<map_wait["Invalid"]<<endl;
    return 0;
}

删除字符串中出现次数最少的字符 牛客华为 HJ23 easy 哈希找最小值

题解:一开始想着删除对应字符,后面想到只需要不输出最少的字符就行

#include
using namespace std;
bool cmp_value(const pair<char, int> left,const pair<char,int> right)
{
	return left.second < right.second;
}
int main(){
    string s,res;
    getline(cin,s);
    int len=s.size();
    unordered_map<char,int> hash;
    for(int i=0;i<len;i++){
       hash[s[i]]++;
    }
    auto j=min_element(hash.begin(),hash.end(),cmp_value);
    for(int i=0;i<len;i++){
      if(hash[s[i]] > j->second)
          res+=s[i];
    }
    cout<<res<<endl;
    return 0;
}

计算字符串中含有的不同字符的个数 牛客华为 HJ10 easy 哈希set

#include
#include
#include
using namespace std;

int main(){
    set<char>hash;
    string s;
    getline(cin,s);
    int len=s.size();
    for(int i=0;i<len;i++){
        if(hash.find(s[i])==hash.end()){
            hash.insert(s[i]);
        }
    }
    cout<<hash.size()<<endl;
}

合并表记录 牛客华为 HJ8 easy 哈希map(有序哈希)哈希的遍历输出

题解: 注意遍历输出hash的手法,注意map输出时会按照key的值进行排序,unordered_map不会,而且是随机的。

#include
#include
using namespace std;
int main(){
    int n,index,value;
    map<int,int>hash;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>index>>value;
        hash[index]+=value;
    }
    for(auto it=hash.begin();it!=hash.end();it++){
        int front = it->first;   //key
        int end = it->second;   //value
        cout<<front<<' '<<end<<endl;
    }
    return 0;
}

数组 两数之和 hot 100 01 easy

题解: 注意hash的语法

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> hash_table;
        int i=0,len=nums.size();
        for(i=0;i<len;i++){
            auto it=hash_table.find(target-nums[i]);
            if(it!=hash_table.end()){
                return{i,it->second};
            }
            hash_table[nums[i]]=i;
        }
        return {};
    }
};

数组 数组中重复的数字 剑指offer 03 easy

题解1: 题解中有用unordered_set的,看看和map有什么不同

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int i=0,len=nums.size();
        unordered_map<int,int> hashtable;
        for(i=0;i<len;i++){
            auto it=hashtable.find(nums[i]);
            if(it!=hashtable.end()){
                return nums[i];
            }
            hashtable[nums[i]]=i;
        }
        return -1;
    }
};

题解2: 通过hash表记录每个数组项出现的次数

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int i=0,len=nums.size();
        unordered_map<int,int> hashtable;
        for(i=0;i<len;i++){
            hashtable[nums[i]]++;
            if(hashtable[nums[i]]==2)
                return nums[i];    
        }
        return -1;
    }
};

数组 数组中出现次数超过三分之一的数字 剑指 Offer 39改编 easy

题解: 原题是超过一半,这样可以直接排序取中值,现在是超过三分之一,可以用哈希记录每个元素出现的次数,注意输入输出的写法

#include 
#include 
#include 
#include 
#include
using namespace std;
class solution {
public:
	int myfun(vector<int>& nums) {
		unordered_map<int, int> hash;
		int res = 0, len = nums.size();
		for (int i = 0; i < len; i++) {
			hash[nums[i]]++;//把hash表想象成一个数组,hash[nums[i]]的初始值为0
			if (hash[nums[i]] >= len / 3)
				return nums[i];
		}
		return -1;
	}
}mysolution;

void main(){
	vector<int> mynums;
	int a;
	while (cin >> a) {
		mynums.push_back(a);
	}
	vector<int>& nums= mynums;
	int ans= mysolution.myfun(nums);
	cout << ans << endl;
}

链表 两个链表的第一个公共节点 剑指offer 52 easy hashmap

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_map<ListNode *,int>hash;
        ListNode *p1=headA,*p2=headB;
        while(p1||p2){
            hash[p1]++;
            hash[p2]++;
            if(p1&&hash[p1]==2){//注意这里的p1&&,排除hash[nullptr]的计数
                return p1;
            }
            if(p2&&hash[p2]==2){//注意这里的p2&&,排除hash[nullptr]的计数
                return p2;
            }
            if(p1)
            p1=p1->next;
            if(p2)
            p2=p2->next;
        }
        return nullptr;
    }
};

工作指针

输出链表倒数第k个节点 华牛 HJ51 easy ACM模式操作链表

题解:注意链表的声明,注意链表的创建,注意如何获取多组输入

#include
using namespace std;
struct ListNode{//注意这里链表定义的手法
int       m_nKey;
ListNode* m_pNext;
ListNode() : m_nKey(0), m_pNext(nullptr) {}
ListNode(int x) : m_nKey(x), m_pNext(nullptr) {}
ListNode(int x, ListNode *next) : m_nKey(x), m_pNext(next) {}
};
int main(){
    struct ListNode * dummy=new(struct ListNode);
    struct ListNode * cur=dummy;
    int n,a,k;
    vector<int>v;
    while(cin>>n){//注意这里循环获取多组输入的手法
        for(int i=0;i<n;i++){
            cin>>a;
            v.emplace_back(a);
        }
        cin>>k;
        int len=v.size();
        for(int i=0;i<len;i++){//注意这里创建链表的手法
            cur->m_pNext=new(struct ListNode);
            cur=cur->m_pNext;
            cur->m_nKey=v[i];
        }
        cur=dummy;
        struct ListNode *slow=cur,*fast=cur;
        for(int i=0;i<k;i++)
            fast=fast->m_pNext;
        while(fast){
            slow=slow->m_pNext;
            fast=fast->m_pNext;
        }
        cout<<slow->m_nKey<<endl;
    }
}

数组 盛水最多的容器 hot 100 11 mid

题解: 双指针,往中间靠,谁小谁移动

class Solution {
public:
    int maxArea(vector<int>& height) {
        int cur_area=0,max_area=0,len=height.size();
        int head=0,tail=len-1;
        while(head!=tail){
            if(height[head]<height[tail]){
                cur_area=height[head]*(tail-head);
                max_area=max(max_area,cur_area);
                head++;
            }
            else{
                cur_area=height[tail]*(tail-head);
                max_area=max(max_area,cur_area);
                tail--;
            }
        }      
        return max_area;
    }
};

数组 三数之和 hot 100 15 mid

题解: 排序,优化版三重for循环,注意for循环中continue和break的用法区别

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        // 枚举 a
        for (int first = 0; first < n; ++first) {
            // 需要和上一次枚举的数不相同
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            // c 对应的指针初始指向数组的最右端
            int third = n - 1;
            int target = -nums[first];
            // 枚举 b
            for (int second = first + 1; second < n; ++second) {
                // 需要和上一次枚举的数不相同
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                // 需要保证 b 的指针在 c 的指针的左侧
                while (second < third && nums[second] + nums[third] > target) {
                    --third;
                }
                // 如果指针重合,随着 b 后续的增加
                // 就不会有满足 a+b+c=0 并且 b
                if (second == third) {
                    break;
                }
                if (nums[second] + nums[third] == target) {
                    ans.push_back({nums[first], nums[second], nums[third]});
                }
            }
        }
        return ans;
    }
};

数组 调整数组顺序使奇数位于偶数前面 剑指 Offer 21 easy

题解: 双指针,交换

class Solution {
public:
    vector<int> exchange(vector<int>& nums) {
        if(nums.size()==0)
            return nums;
        int i=0,len=nums.size();
        int head=0,tail=len-1;
        int swap=0;
        while(head!=tail){
            if(nums[tail]%2==0){
                tail--;
            }
            else{
                swap=nums[head];
                nums[head]=nums[tail];
                nums[tail]=swap;
                head++;
            }
        }
        return nums;
    }
};
class Solution {
public:
    char firstUniqChar(string s) {
            vector<int> m(26,0);
            int i=0,len=s.size();
            for(i=0;i<len;i++){
                m[s[i]-'a']++;
            }
            for(i=0;i<26;i++){
                if(m[i]==1)
                return (char)('a'+i);
            }
            return ' ';
    }
};

链表 两个链表的第一个公共节点 剑指offer 52 easy 有点类似快慢指针

题解: 两个跑速不同的人如何相遇,答,不断交换跑道,注意这里就算没有交点,也会同时等于nullptr

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) {
            return nullptr;
        }
        ListNode *pA = headA, *pB = headB;
        while (pA != pB) {
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        return pA;
    }
};

数学计算、位运算

一个float数四舍五入取近似值 华牛 HJ7 easy

#include
using namespace std;
int main(){
    float x;
    cin >> x;
    cout << (int)(x+0.5) << endl; //强制类型转换,默认向下取整
    return 0;
}

一个整数的所有质数因子 华牛 HJ6 easy

#include
using namespace std;
int main(){
    long n;
    cin >> n;
    for(long i = 2; i <= sqrt(n) && i <= n; i++){  //从小到大的质因子,质因子不会超过它的开方
        while(n % i == 0){ //所有的质数前面全部除掉,后续就不会有合因子
            cout << i << " ";
            n /= i; //除掉质因子
        }
    }
    if(n - 1) //自己本身就是质数
        cout << n << " ";
    return 0;
}

int二进制数中连续的1的个数 华牛 HJ86 easy

#include 
#include 
using namespace std;
int main(){
    int n,cnt=0;
    while(cin>>n){
        while(n){
            n=n&(n<<1);
            cnt++;
        }
        cout<<cnt<<endl;
        cnt=0;
    }
    return 0;
}

二进制中1的个数 剑指offer 15 easy

题解1:

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int cnt=0;
        for(int i=0;i<32;i++){
            if((n&1)==1){
                cnt++;
            }
            n=n>>1;
        }
        return cnt;
    }
};

题解2: 书上的简便方法

int hammingWeight(uint32_t n) {
    int cnt=0;
    while(n)
    {
        n=n&(n-1);
        cnt++;
    }
    return  cnt;
}

你可能感兴趣的:(数据结构与算法,嵌入式求职,leetcode,算法,java)