算法刷题小技巧【持续补充~】

🕺作者: 主页

我的专栏
C语言从0到1
探秘C++
数据结构从0到1
探秘Linux

😘欢迎 ❤️关注 👍点赞 🙌收藏 ✍️留言

文章目录

    • 前言
      • 使用scanf格式化读取数据
      • 输入字符串 getline
        • cin.getline() 使用举例
        • 两种getline函数
        • getline使用举例
      • 输入多行字符串(行数未知)
      • 截断字符串
      • 字符串转浮点数 stof函数
        • PAT甲级真题1108 求平均值
        • 输入格式
        • 输出格式
        • 数据范围
        • 输入样例1:
        • 输出样例1:
        • 输入样例2:
        • 输出样例2:
        • 题解
      • 对二维数组去重

前言

欢迎提供新技巧,可在评论区留言~

使用scanf格式化读取数据

eg:

scanf("%d.%d.%d %d.%d.%d",&a,&b,&c,&d,&e,&f);
//可以读取数据格式为1.2.4 2.14.15

输入字符串 getline

使用getline函数:
cin.getline()也是常用的读取整行string的方式。
getline()操作的对象是string,cin.getline()操作的对象的char数组
cin.getline()函数读取至新行结尾或直到达到最大限制的整行文本。函数定义如下:

// (buffer, stream_size, delimiter)
istream& getline(char*, int size, char='\n')// The delimiter character is considered as '\n'
istream& getline(char*, int size)
  1. 提取字符直到定界符。
  2. 将字符存储在缓冲区中。
  3. 提取的最大字符数为size-1。
cin.getline() 使用举例
#include <iostream> 
using namespace std; 
int main() 
{ char str[20]; cin.getline(str, 20); cout << str; return 0; 
}
两种getline函数
有两种getline函数:
库函数 string 和 iostream 均有getline函数#include<string> // 全局的函数
istream& getline (istream& is, string& str, char delim);
istream& getline (istream& is, string& str);#include <iostream> // 成员函数
istream& getline (char* s, streamsize n);
istream& getline (char* s, streamsize n, char delim);注意iostream的getline是将读取的字符串存储在char数组中而不可以将该参数声明为string类型,
因为C++编译器无法执行此默认转换。
getline使用举例
#include <iostream>
#include <string>
using namespace std;
int main() {string s;getline(cin, s);cout << s;	system("pause");return 0;
}		

输入多行字符串(行数未知)

string str;
vector<string> v;
while (getline(cin, str)) //读取输入的一行数据
{if (str.size() == 0) break; //如果读取的是空,则读取结束v.push_back(str);
}

截断字符串

substr:返回一个从指定位置开始的指定长度的子字符串

stringvar.substr(start, [length])
/*
参数
stringvar   必选项。要提取子字符串的字符串文字或 String 对象。
start       必选项。所需的子字符串的起始位置。字符串中的第一个字符的索引为 0。
length      可选项。在返回的子字符串中应包括的字符个数。说明
如果 length 为 0 或负数,将返回一个空字符串。如果没有指定该参数,则子字符串将延续到 stringvar 的最后。
*/

字符串转浮点数 stof函数

使用方法和stoi函数一样
stof判断"5.2abc"这类字符串时视"5.2"为合法,"abc"不合法,但实际上5.2abc不合法

举例:

PAT甲级真题1108 求平均值

基本任务非常简单:给定 N 个实数,请你计算它们的平均值。
但是令事情变得复杂的是,某些输入数字可能不合法。
合法输入数字指 [−1000,1000] 范围内的精确到不超过 2 个小数位的实数。
在计算平均值时,不得将这些非法数字计算在内。

输入格式

第一行包含整数 N。
第二行包含 N 个输入数字,数字之间用空格隔开。

输出格式

按照输入的顺序,对于每个输入的非法数字,在一行中输出 ERROR: X is not a legal number,其中 X 是非法输入。
最后一行,输出 The average of K numbers is Y,其中 K 是合法输入的数量,Y 是它们的平均值,注意保留两位小数。
如果平均值无法计算,则将 Y 替换为 Undefined
如果 K 仅为 1,则输出 The average of 1 number is Y

数据范围

1≤N≤1000

输入样例1:
7
5 -3.2 aaa 9999 2.3.4 7.123 2.35
输出样例1:
ERROR: aaa is not a legal number
ERROR: 9999 is not a legal number
ERROR: 2.3.4 is not a legal number
ERROR: 7.123 is not a legal number
The average of 3 numbers is 1.38
输入样例2:
2
aaa -9999
输出样例2:
ERROR: aaa is not a legal number
ERROR: -9999 is not a legal number
The average of 0 numbers is Undefined
题解
//@魔法学徒:https://www.acwing.com/user/myspace/index/162238/
#include <iostream>
using namespace std;int main()
{int n;cin >> n;int cnt = 0;    // 合法数字个数double sum = 0; // 合法数字总和while (n -- ){string num;cin >> num;double x;bool success = true;/*不加try catch报错terminate called after throwing an instance of 'std::invalid_argument' what():  stof(若传入不可转化为浮点型的字符串)会抛出异常*/try{size_t idx = sizeof(num); // size type 用来记录大小的数据类型x = stof(num, &idx);      // 字符串转换为float型// stof判断"5.2abc"这类字符串时视"5.2"为合法,"abc"不合法,但实际上5.2abc不合法if (idx < num.size()) success = false; // 经stof处理后变短的字符串不合法}catch(...)                    // 捕捉所有类型的异常 {success = false;          // 所有不合法的输入数字都设为error}if (x < -1000 || x > 1000) success = false;int k = num.find('.');if (k != -1 && num.size() - k > 3) success = false;// 不超过2个小数位(最后一位是num.size()-1)if (success) cnt ++, sum += x;else printf("ERROR: %s is not a legal number\n", num.c_str());}if (cnt > 1) printf("The average of %d numbers is %.2lf\n", cnt, sum / cnt);else if (cnt == 1) printf("The average of 1 number is %.2lf\n", sum);else puts("The average of 0 numbers is Undefined");return 0;
}

对二维数组去重

    std::vector<std::vector<int>> removeDuplicates(const std::vector<std::vector<int>>& arr) {std::vector<std::vector<int>> sortedArr = arr;// 对二维数组排序std::sort(sortedArr.begin(), sortedArr.end());// 去除重复项auto last = std::unique(sortedArr.begin(), sortedArr.end());sortedArr.erase(last, sortedArr.end());return sortedArr;}

在上述代码中,std::unique 函数用于去除连续的重复项,该函数位于 <algorithm> 头文件中。函数的原型如下:

template<class ForwardIt>
ForwardIt unique(ForwardIt first, ForwardIt last);

其中,firstlast 是表示要处理的元素范围的迭代器,ForwardIt 是一个泛型类型。std::unique 函数会返回一个指向最后一个不重复元素之后位置的迭代器。这意味着,从 firstlast 的范围内的所有连续重复元素都被移到了范围的末尾,并且返回的迭代器指向了新范围的终点。

在代码中,我们使用 std::unique 函数将数组 sortedArr 中的重复项移到了末尾,并将返回的迭代器保存在 last 变量中。然后,我们使用 erase 函数将重复项从数组中删除,其原型如下:

template<class Container, class Iterator>
Iterator erase(Container& cont, Iterator pos);

其中,cont 是容器,pos 是指向要删除元素位置的迭代器。erase 函数会从容器中删除指定位置的元素,并返回一个指向被删除元素之后位置的迭代器。

在我们的代码中,sortedArr 是一个二维向量,我们使用 erase 函数将 lastsortedArr.end() 范围内的元素从 sortedArr 中删除,即删除了末尾的重复项。

通过上述操作,我们使用 std::unique 函数和 erase 函数成功去除了二维数组中的连续重复项。