C++练习1:活用vector、string和map

本文介绍了使用C++中的vector、string和map解决力扣及剑指Offer中的经典编程问题,包括合法用户名检查、查找数组中重复数字、排序数组中数字出现次数、缺失数字定位、二维数组查找、旋转数组最小值和首次出现一次的字符等挑战,通过实例解析算法思路和实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

力扣meituan-001. 小美的用户名

几个常用的宏定义:

  1. isalpha() 用来判断一个字符是否为字母,如果是字符则返回非零,否则返回零
  2. isalnum() 用来判断一个字符是否为数字或者字母,也就是说判断一个字符是否属于a~z||A~Z||0~9
  3. isdigit() 用来判断一个字符是否为数字
  4. islower() 用来判断一个字符是否为小写字母,也就是是否属于a~z
  5. isupper()islower 相反,用来判断一个字符是否为大写字母

题目:
小美是美团的前端工程师,为了防止系统被恶意攻击,小美必须要在用户输入用户名之前做一个合法性检查,一个合法的用户名必须满足以下几个要求:

用户名的首字符必须是大写或者小写字母。
用户名只能包含大小写字母,数字。
用户名需要包含至少一个字母和一个数字。
如果用户名合法,请输出 “Accept”,反之输出 “Wrong”。
在这里插入图片描述

解题:

#include <iostream>
#include <string>
#include <vector>     // 动态数组
using namespace std;

int main(){
    int T;
    cin >> T;
    vector<string> res;     // 定义返回字符串顺序容器
    while(T--){
        string name;
        cin >> name;
        if(!isalpha(name[0]))    // 首字母不是字母。输出wrong
        {
            res.push_back("Wrong");
            continue;     // 直接下一个
        }
        // 遍历所有字符
        int flag = 0;    // 做标记,有数字flag记为1
        int flag1 = 0;
        for(int i=0; i<name.length(); i++){
            if(!isalnum(name[i])){    // 特殊字符
                res.push_back("Wrong");
                flag1 = 1;
                break;   // 只是退出当前for循环
            }
            if(isdigit(name[i])){
                flag = 1;
                continue;
            }
        }
        // 有特殊字符的情况,直接下一个,避免下面重复输出
        if(flag1 == 1) continue;
        // 如果没有数字,且
        if(flag == 0){
            res.push_back("Wrong");
            continue;
        }
        // 其他情况都输出accept
        res.push_back("Accept");
    }
    // 输出r中的字符
    for(auto r : res){
        cout << r << endl;
    }
}

剑指 Offer 03. 数组中重复的数字

题目:
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:
输入:[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3

解题:

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        map<int,bool> dict;       // map关联容器
        for(int r:nums){           // 这里的r和C语言中的arr[i]是一个道理
            if(dict[r]) return r;   // 如果是1,就返回。
            dict[r]=true;
        }
        return -1;
    }
};

剑指 Offer 53 - I. 在排序数组中查找数字 I

题目:
统计一个数字在排序数组中出现的次数。
在这里插入图片描述

解题:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int count=0;
        for(int r:nums){
            if(r==target){
                count++;
            }
        }
        return count;
    }
};

剑指 Offer 53 - II. 0~n-1中缺失的数字

题目:
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
在这里插入图片描述

解题:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int i=0;
        for(int r:nums){
            if(r!=i){
                return i;
            }
            ++i;
        }
        return nums.size();
    }
};

剑指 Offer 04. 二维数组中的查找

题目:
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
在这里插入图片描述

解题:

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int i = matrix.size()-1, j = 0;             // matrix.size()表示行数
        while(i>=0 && j<matrix[0].size()){          // matrix[0].size表示列数
            if(matrix[i][j] > target){
                i--;
            }else if(matrix[i][j] < target){
                j++;
            }else{
                return true;
            }
        }
        return false;
    }
};

剑指 Offer 11. 旋转数组的最小数字

题目:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
在这里插入图片描述

解题:
旋转数组是由两个分别有序的数组组合在一起的,并有分界点,分界点的右侧就是要找的点。

  1. 暴力法:相邻元素比较,找到下一个元素小于当前元素的的位置,不推荐;
  2. 二分法:
    中间数比右边界大,则分界点在右边部分,左边界=中间位+1
    中间数比右边界小,则分界点在左边部分,右边界=中间位
    中间数和右边界相等,则右边界暴力向左移动1
    直到左边界等于由边界,结束循环,返回边界值
class Solution {
public:
    int minArray(vector<int>& numbers) {
        int left = 0;
        int right = numbers.size()-1;
        while(right>left){
            int mid = left + (right - left)/2;
            if(numbers[mid] > numbers[right]){
                left = mid + 1;
            }else if(numbers[mid] < numbers[right]){
                right = mid;
            }else{
                right--;
            }
        }
        return numbers[left];
    }
};

剑指 Offer 50. 第一个只出现一次的字符

题目:
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
在这里插入图片描述

解题:

class Solution {
public:
    char firstUniqChar(string s) {
        map<char,bool> dic;
        for(char c:s){
            if(dic.find(c) != dic.end()){     // 如果能找到,即有重复的
                dic[c] = false;             // map值置为0
            }else{                          // 如果找不到,即没有重复的
                dic[c] = true;              // map值写下1
            }
        }
        for(char c:s){
            if(dic[c] == true){
                return c;               // 找到第一个没有重复的,返回值
            }
        }
        return ' ';
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值