你有没有被面试官说过:你这个STL了解的不够啊。。有没有看到同样是C++为什么别人的代码还能那么少。。。好吧玄机都在#include<algorithm>里面。官方函数使用方法:http://www.cplusplus.com/reference/algorithm/
考试用#include<bits/stdc++.h>万能头文件好了
常用功能:交换swap,逆序reverse ,旋转rotate,排序sort,排列组合permutation,查找find,划分(partition)去重set vec(不是alg的),统计count,初始化fill(不是alg的)
目录
5. 优先级队列、大根堆、小根堆、priority_queue / multiset / multimap
5. 利用set为vector数组去重(set(vec.begin(), vec.end()))
1. 交换两个元素 swap(arr[1], arr[2]);//直接交换不用&换地址
rotate(vec.begin(),vec.begin()+3,vec.end())前面3个移到后面
rotate_copy(input.first(),input.middle,input.last(),res.first())
4. std::sort(str.begin(),str.end(),cmp);某认从小到大
vector排序,按照字典序(ASCII 码值)排序,不用管长度
自定义排序示例,bool cmp(string qian,string hou);qian,从小到大<>
其他排序方式的实现 (struct中bool operator() (int i,int j))
5. 是否是用一个父产生的排序 is_permutation
6. 按字典序的上/下一个排列 next_permutation(start(),end(),cmp)
8. 查找find ,find_first_of , find_if , adjacent_find(二分可用)
find(vec.begin(),vec.end(),value); 本身就是查找第一个
find_first_of (r1.begin(),r1.end(),r2.begin(),r2.end()) 在r1中查找第一个r2中的元素
find_if(first,end,pre) pre是一个bool的判断谓词
adjacent_find 用于查找相等或满足条件的邻近元素对
9. 前后划分partition/stable_partition(如:奇数在前,偶数在后。前后的这种划分)
10. 计数count(a.begin(),a.end(),value)
count_if(a.begin(),a.end(),pre)
11. 容器相等equal (I1 first1, I1 last1, I2 first2, pred);pre可有可无
12. 替换 replace_if (v.begin(), v.end(), IsOdd, 0)
13. 移除 std::remove_if (pbegin, pend, IsOdd);
14. 随机打乱 std::random_shuffle ( v.begin(), v.end() );
来一道今年前些天华为的真题试试威力(字符串输入合法非法去重左移外排)
再插几条新闻(常错和捡漏)
1. map
- mymap.count(key)key的个数
- map.begin的用法
for ( auto it = mymap.begin(); it != mymap.end(); ++it )
std::cout << " " << it->first << ":" << it->second;
-
map.find的用法,而不是find(map.begin()...)
it = mymap.find('b'); if (it != mymap.end()) mymap.erase (it);
- map::lower_bound(不小于的第一个索引)/upper_bound(这里的map是有序的,自动按照key值排序,所以可以截取的删除)而且删除了开头,结尾闭区间《algorithm中也有,map之所以自带,是因为本身就是有序的,vec没有自带,需要sort之后,然后用algorithm中的》
mymap['a']=20;mymap['b']=40;mymap['c']=60;
mymap['d']=80;mymap['e']=100;
itlow=mymap.lower_bound ('b'); // itlow points to b
itup=mymap.upper_bound ('d'); // itup points to e (not d!)
mymap.erase(itlow,itup); // erases [itlow,itup)
for (std::map<char,int>::iterator it=mymap.begin(); it!=mymap.end(); ++it)
std::cout << it->first << " => " << it->second << '\n';
out:
a => 20
e => 100
- swap(直接交换两个map)
std::map<char,int> foo,bar;
foo['x']=100;
foo['y']=200;
bar['a']=11;
bar['b']=22;
bar['c']=33;
foo.swap(bar);
foo contains:
a => 11
b => 22
c => 33
bar contains:
x => 100
y => 200
2. queue
注意是front,priority_queue中是top。
3. algorithm
- lower_bound (不小于 大于等于的第一个索引)/ upper_bound(大于的第一个索引) 核心是二分做的,要求之前sort
std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30
std::vector<int>::iterator low,up;// 索引
low=std::lower_bound (v.begin(), v.end(), 20); // ^
up= std::upper_bound (v.begin(), v.end(), 20); // ^
int pos3=lower_bound(num,num+6,7,greater<int>())-num; //返回数组中第一个小于或等于被查数的值 int pos4=upper_bound(num,num+6,7,greater<int>())-num; //返回数组中第一个小于被查数的值
- binary_search二分查找是否存在,返回bool
- 求交、求并、求差 set_intersection set_union set_difference,必须先sort,返回迭代器it配合vec.resize(it-vec.begin)使用
set_intersection (first, first+5, second, second+5, v.begin())
int first[] = {5,10,15,20,25};
int second[] = {50,40,30,20,10};
std::vector<int> v(10); // 0 0 0 0 0 0 0 0 0 0
std::vector<int>::iterator it;
std::sort (first,first+5); // 5 10 15 20 25
std::sort (second,second+5); // 10 20 30 40 50
// it只想最后一个交集
it=std::set_intersection (first, first+5, second, second+5, v.begin());
// resize(2)变成2个
// 10 20 0 0 0 0 0 0 0 0
v.resize(it-v.begin()); // 10 20
4. string
push_back 和 pop_back
if(str.find_first_of('a')==-1)如果没有找到该字符
str.erase(str.begin() + right);
5. 优先级队列、大根堆、小根堆、priority_queue / multiset / multimap
priority_queue <int> 默认从大到小(大根堆)
std::priority_queue<int> mypq;
mypq.push(30);
mypq.push(100);
mypq.push(25);
mypq.push(40);
std::cout << "Popping out elements...";
while (!mypq.empty())
{
std::cout << ' ' << mypq.top();
mypq.pop();
}
std::cout << '\n';
priority_queue <int,vector<int>,greater<int>>小根堆 greater在functional头文件当中
priority_queue<ListNode*,vector<ListNode*>,cmp> 对链表进行大根堆
struct cmp {// 小根堆~!~~~~~~ 这里是ListNode是结构体,必须这么写
bool operator()(ListNode* l1, ListNode* l2) {
return l1->val > l2->val;
}
};
priority_queue里面是top不是front了。而且priority_queue中的greater和set中的正相反。
--------------------------------------------------------------------------------------
multiset<int, greater<int>> greadterSet; 9 9 8 7 7 5 4 1 0 0
multiset<int, less<int>> lessSet; 0 0 1 4 5 7 7 8 9 9 // 这里less是小根堆,优先级队列相反
multiset<int> defaultSet; 0 0 1 4 5 7 7 8 9 9 // 默认小根堆
---------------------------------------------------------------------------------------
使用mutimap代替优先队列,mutimap会自动对key从小到大排序,可以免去编写比较函数的麻
multimap<int, ListNode*> headMap;key从小到大排序 默认
multimap<int, ListNode*,greater<int>>headMap
插播两条新闻
1. erase函数 左闭右开:
(1)erase(pos,n); 删除从pos开始后的n个字符,比如erase(0,1)就是删除第一个字符
(2)erase(position);删除position处的一个字符(position是个string类型的迭代器)
(3)erase(first,last);删除从first到last之间的字符(first和last都是迭代器) 左闭右开
// string::erase
#include <iostream>
#include <string>
int main ()
{
std::string str ("This is an example sentence.");
std::cout << str << '\n';
// "This is an example sentence."
str.erase (10,8); // ^^^^^^^^
std::cout << str << '\n';
// "This is an sentence."
str.erase (str.begin()+9); // ^
std::cout << str << '\n';
// "This is a sentence."
str.erase (str.begin()+5, str.end()-9); // ^^^^^
std::cout << str << '\n';
// "This sentence."
return 0;
}
2. char 变成 int ('10'-'0')
'10'->10 '10'-'0'
3. 字符串拼接 9后面跟着n个0 (直接+=)
9后面跟着n个0
string a="9";
string b="0"
for(int i =0;i<n;i++){
a+=b;
}
4. cctype
不常用的勾掉了。右图显示了char的while的使用
5. 利用set为vector数组去重(set(vec.begin(), vec.end()))
set<int> st(vec.begin(), vec.end());
vec.assign(st.begin(), st.end());#用其他的模块初始化
vector<int>vec(st.begin(), st.end());//声明的时候直接初始化,都可以这样
vector<int> vec;
vec = { 1, 2, 3, 4, 8, 9, 3, 2, 1, 0, 4, 8 };
set<int> st(vec.begin(), vec.end());
vec.assign(st.begin(), st.end());#用其他的模块初始化
1. 交换两个元素 swap(arr[1], arr[2]);//直接交换不用&换地址
这个需要注意的是std中也有swap, 当你引入algorithm和std之后,用swap时可以加入std::swap
int arr[1,2,3,4];
swap(arr[1], arr[2]);//直接交换不用&换地址
2. 反转元素的次序 reverse()
-
全部逆序
string str("hello");
//如何才能只反转ello,即变成holle?如下
reverse(str.begin()+1,str.end());
-
部分逆序,实现左移n为字符串的功能
如:abcdef,左移2,是cdefab
reverse(str.begin(),str.begin()+2);
reverse(str.begin()+2,str.end());
reverse(str.begin(),str.end());
3. rotate/rotate_copy旋转
其实和上面的用reverse实现的左移的功能是一样的。
rotate(vec.begin(),vec.begin()+3,vec.end())前面3个移到后面
template <class ForwardIterator>
void rotate (ForwardIterator first, ForwardIterator middle,
ForwardIterator last)
{
ForwardIterator next = middle;
while (first!=next)
{
swap (*first++,*next++);
if (next==last) next=middle;
else if (first==middle) middle=next;
}
}
int main () {
std::vector<int> myvector;
// set some values:
for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
std::rotate(myvector.begin(),myvector.begin()+3,myvector.end());
// 4 5 6 7 8 9 1 2 3
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
rotate_copy(input.first(),
input.middle,
input.last(),res.first()
)
template <class ForwardIterator, class OutputIterator>
OutputIterator rotate_copy (ForwardIterator first, ForwardIterator middle,
ForwardIterator last, OutputIterator result)
{
result=std::copy (middle,last,result);
return std::copy (first,middle,result);
}
int main () {
int myints[] = {10,20,30,40,50,60,70};
std::vector<int> myvector (7);
std::rotate_copy(myints,myints+3,myints+7,myvector.begin());
// print out content:
std::cout << "myvector contains:";
for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
myvector contains: 40 50 60 70 10 20 30
4. std::sort(str.begin(),str.end(),cmp);某认从小到大
是一种根据实际数据智能选择排序算法的函数,sort()会将区间[beg,end)内的元素排序,默认升序
sort(v.begin(), v.end()); //实现排序,正序排列
bool cmp(int a,int b)
{
return a>b;//降序排列
}
int array[5]={1,2,3,4,5};
sort(array,array+4,cmp);//通过自定义cmp函数将其改为降序排序
输出为:4 3 2 1 5
-
string内部排序
sort(str.begin(),str.end());
-
vector<string>排序,按照字典序(ASCII 码值)排序,不用管长度
先放到vector<string>vec当中
然后sort(vec.begin(),vec.end());
-
自定义排序示例,bool cmp(string qian,string hou);qian<hou,从小到大
题目大致是:输入若干行由0和1组成的串,将这些串排序输出。
排序规则是:首先按长度排序,长度相同时,按1 的个数多少进行排序,1 的个数相同时再按ASCII 码值排序。
bool cmp(string s1, string s2)
{
int t1 = count(str1.begin(),str1.end(), '1');
int t2 = count(str2.begin(),str2.end(), '1');
if(s1.length() !=s2.length())
{
return s1.length() <s2.length();
}
return (t1 != t2 ? t1 < t2: s1 < s2);
}
int main()
{
……
sort(s.begin(), s.end(), cmp);
……
return 0;
}
-
其他排序方式的实现 (struct中bool operator() (int i,int j))
struct myclass {
bool operator() (int i,int j) {
return (i<j);
}
} myobject;
std::sort (vec.begin(), vec.end(), myobject);
5. 是否是用一个父产生的排序 is_permutation
将range [first1,last1]中的元素与以first2开头的元素进行比较,如果两个范围中的所有元素都匹配,即使顺序不同,也会返回true。
std::array<int,5 foo = {1,2,3,4,5};
std::array<int,5> bar = {3,1,4,5,2};
std::is_permutatio cegin()) 这两个是相等的。
6. 按字典序的上/下一个排列 next_permutation(start(),end(),cmp)
按字典序的下一个排列next_permutation
(),按字典序的前一个排列 prev_permutation
(),需要先将其sort升序排列好,再用
do//do-while循环和next_permutation、prev_permutation更配喔~
{
res.push_back(str);
}while(next_permutation(str.begin(),str.end()));
//next_permutation()执行一次 当前的str序列abc 就变成了 升序中的下一个str序列acb
//当 当前的str序列 是 最后一种str序列cba ,那么它就会变成最初的str序列abc
-
部分排列
while(next_permutation(num,num+3))中的3改为2时,输出就变为了:
-
自定义排列的顺序。
如修改字典序为:'A'<'a'<'B'<'b'<...<'Z'<'z'.请按照这个依次写出排列的内容。
//我把cmp中char a看成是前一个内容,b是后一个内容,return a<b,返回ture,前比后小,做升序的
bool cmp(char a,char b)
{//如果转换成统一的,不相等,那嚒按照转换后的排序就好了
if(tolower(a)!=tolower(b))//tolower 是将大写字母转化为小写字母.
return tolower(a)<tolower(b);
else
return a<b;//说明是同一个字母的大小写,直接就好,
}
7. 字典序lexicographical_compare
lexicographical_compare(first.begin(),first.end(),last.begin(),last.end(),cmp)默认ascii码从小到大,默认前小,返回true
// lexicographical_compare example
#include <iostream> // std::cout, std::boolalpha
#include <algorithm> // std::lexicographical_compare
#include <cctype> // std::tolower
// a case-insensitive comparison function:
bool mycomp (char c1, char c2)
{ return std::tolower(c1)<std::tolower(c2); }
int main () {
char foo[]="Apple";
char bar[]="apartment";
// 默认ascii的话,第一个A<a,不用看后面的了,第一个已经小了,所以返回true
std::cout << std::boolalpha;
std::cout << "Comparing foo and bar lexicographically (foo<bar):\n";
std::cout << "Using default comparison (operator<): ";
std::cout << std::lexicographical_compare(foo,foo+5,bar,bar+9);
std::cout << '\n';
std::cout << "Using mycomp as comparison object: ";
std::cout << std::lexicographical_compare(foo,foo+5,bar,bar+9,mycomp);
std::cout << '\n';
return 0;
}
8. 查找find ,find_first_of , find_if , adjacent_find(二分可用)
-
find(vec.begin(),vec.end(),value); 本身就是查找第一个
vector<int>::itertation iter = find(vec.begin(),vec.end(),value);
if(iter!=vec.end())
//说明存在,iter就是地址,*iter就是value,
//这个是因为,函数设定成这样了,如果find不存在,自动返回vec.end()的地址。
类似地,由于指针的行为与作用在内置数组上的迭代器一样,因此也可以使用find来搜索数组:
int ia[6] = {27 , 210 , 12 , 47 , 109 , 83};
int search_value = 83;
int *result = find(ia , ia + 6 , search_value);
cout<<"The value "<<search_value<<(result == ia + 6 ? " is not present" : "is present")
-
find_first_of (r1.begin(),r1.end(),r2.begin(),r2.end()) 在r1中查找第一个r2中的元素
roster1可以是list对象,而roster2则可以是vector对象、 deque对象或者是其他序列。只要这两个序列的的元素可使用相等(==)操作符进行比较即可。如果roster1是list< string>对象,则roster2可以使vector<char*>对象,因为string标准库为string对象与char* 对象定义了相等(==)操作符。
这个算法带有两对迭代器参数来标记两端元素范围:第一段范围内查找与第二段范围中任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素。如果找不到匹配元素,则返回第一个范围的end迭代器。
假设roster1和roster2是两个存放名字的list对象,可使用find_first_of统计有多少个名字同时出现在这两个列表中:
size_t cnt = 0;
list<string>::iterator it = roster1.begin();
// look in roster1 for any name also in roster2
while((it = find_first_of(it , roster1.end() , roster2.begin() , roster2.end())) != roster1.end())
{
++cnt;
// we got a match , increment it to look in the rest of roster1
++it;
}
cout<<"Found "<<cnt<<" names on both rosters "<<endl;
-
find_if(first,end,pre) pre是一个bool的判断谓词
//谓词判断函数 divbyfive : 判断x是否能5整除
bool divbyfive(int x)
{return x % 5 ? 0 : 1;}
-
adjacent_find 用于查找相等或满足条件的邻近元素对
参考自:https://blog.csdn.net/hyg0811/article/details/10390591
bool myfunction (int i, int j) {
return (i==j);//前一个等于后一个
}
int main () {
int myints[] = {5,20,5,30,30,20,10,10,20};
std::vector<int> myvector (myints,myints+8);
std::vector<int>::iterator it;
// using default comparison:
it = std::adjacent_find (myvector.begin(), myvector.end());
if (it!=myvector.end())
std::cout << "the first pair of repeated elements are: " << *it << '\n';
//using predicate comparison:
it = std::adjacent_find (++it, myvector.end(), myfunction);
if (it!=myvector.end())
std::cout << "the second pair of repeated elements are: " << *it << '\n';
return 0;
}
Output:
the first pair of repeated elements are: 30
the second pair of repeated elements are: 10
9. 前后划分partition/stable_partition(如:奇数在前,偶数在后。前后的这种划分)
- partition是会打乱原先的顺序,stable_partition则不会
- 和std:: partition不同的是,stable_partition是稳定的,保持原有元素的相对顺序。
双向迭代器 BidirectionalIterator stable_partition (BidirectionalIterator first, BidirectionalIterator last, UnaryPredicate pred)
返回值:指向第二组(哪些使pred返回false)第一个元素的迭代器,或者第二组为空,返回last.
如:奇数在前,偶数在后,传统的方法,是定义前后指针,前面的指针如果指向的值是奇数就遍历,偶数就不动(while),后指针,如果指向的是偶数就遍历,奇数就不动,然后再前后交换,使得奇数在前,偶数在后,但是会发生位置的相对变化。利用partition的方法。
bool IsOdd (int i) { return (i%2)==1; }
int main () {
std::vector<int> myvector;
// set some values:
for (int i=1; i<10; ++i) myvector.push_back(i); // 1 2 3 4 5 6 7 8 9
std::vector<int>::iterator bound;
bound = std::stable_partition (myvector.begin(), myvector.end(), IsOdd);
// print out content:
std::cout << "odd elements:";
for (std::vector<int>::iterator it=myvector.begin(); it!=bound; ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "even elements:";
for (std::vector<int>::iterator it=bound; it!=myvector.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
odd elements: 1 3 5 7 9
even elements: 2 4 6 8
10. 计数count(a.begin(),a.end(),value)
-
count_if(a.begin(),a.end(),pre)
bool IsOdd (int i) { return ((i%2)==1); }
11. 容器相等equal (I1 first1, I1 last1, I2 first2, pred);pre可有可无
// equal algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::equal
#include <vector> // std::vector
bool mypredicate (int i, int j) {
return (i==j);
}
int main () {
int myints[] = {20,40,60,80,100}; // myints: 20 40 60 80 100
std::vector<int>myvector (myints,myints+5); // myvector: 20 40 60 80 100
// using default comparison:
if ( std::equal (myvector.begin(), myvector.end(), myints) )
std::cout << "The contents of both sequences are equal.\n";
else
std::cout << "The contents of both sequences differ.\n";
myvector[3]=81; // myvector: 20 40 60 81 100
// using predicate comparison:
if ( std::equal (myvector.begin(), myvector.end(), myints, mypredicate) )
std::cout << "The contents of both sequences are equal.\n";
else
std::cout << "The contents of both sequences differ.\n";
return 0;
}
12. 替换 replace_if (v.begin(), v.end(), IsOdd, 0);
13. 移除 std::remove_if (pbegin, pend, IsOdd);
14. 随机打乱 std::random_shuffle ( v.begin(), v.end() );
15. 构建大根堆
一是在找k个小的树的时候
第一种直接构建相关变量
第二种利用push_heap,pop_heap的操作,将一个vector弄成大根堆。
形式一:
typedef multiset<int,greater<int>> intSet;#直接定义个大根堆
typedef multiset<int,greater<int>>::iterator intSetIter;
intSet& leastNumbers,如果leastNumbers<k直接插入,如果大于k,如果大于k,看*iter,如果小于堆顶的数,删除erase堆顶 leastNumbers.begin(),插入该数。
// ====================方法1====================
// ====================方法2====================
typedef multiset<int, std::greater<int> > intSet;
typedef multiset<int, std::greater<int> >::iterator setIterator;
void GetLeastNumbers_Solution2(const vector<int>& data, intSet& leastNumbers, int k)
{
leastNumbers.clear();
if(k < 1 || data.size() < k)
return;
vector<int>::const_iterator iter = data.begin();
for(; iter != data.end(); ++ iter)
{
if((leastNumbers.size()) < k)
leastNumbers.insert(*iter);
else
{
setIterator iterGreatest = leastNumbers.begin();
if(*iter < *(leastNumbers.begin()))
{
leastNumbers.erase(iterGreatest);
leastNumbers.insert(*iter);
}
}
}
}
形式二:
利用函数和vector弄
先定义私有成员变量 vector<int> max;
利用push_heap pop_heap的方式结合vector.pop_back()的方法
max.push_back(num);
push_heap(max.begin(), max.end(), less<T>());
num = max[0];##记录堆顶
pop_heap(max.begin(), max.end(), less<T>());##堆顶和最后的互换
max.pop_back();##弹出最后一个 上两个结合heapify
min.push_back(num);
push_heap(min.begin(), min.end(), greater<T>());
template<typename T> class DynamicArray
{
public:
void Insert(T num)
{
if(((min.size() + max.size()) & 1) == 0)
{
if(max.size() > 0 && num < max[0])
{
max.push_back(num);
push_heap(max.begin(), max.end(), less<T>());
num = max[0];
pop_heap(max.begin(), max.end(), less<T>());
max.pop_back();
}
min.push_back(num);
push_heap(min.begin(), min.end(), greater<T>());
}
else
{
if(min.size() > 0 && min[0] < num)
{
min.push_back(num);
push_heap(min.begin(), min.end(), greater<T>());
num = min[0];
pop_heap(min.begin(), min.end(), greater<T>());
min.pop_back();
}
max.push_back(num);
push_heap(max.begin(), max.end(), less<T>());
}
}
T GetMedian()
{
int size = min.size() + max.size();
if(size == 0)
throw exception("No numbers are available");
T median = 0;
if((size & 1) == 1)
median = min[0];
else
median = (min[0] + max[0]) / 2;
return median;
}
private:
vector<T> min;
vector<T> max;
};
来一道今年前些天华为的真题试试威力(字符串输入合法非法去重左移外排)
图片摘自网络
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <ctype.h>
#include<set>
using namespace std;
int main() {
vector<string>valid_vec;//有效的字符串
vector<string>invalid_vec;//无效字符串
char input[100];
do{// 判断是否 输入结束了
cin.getline(input, 100);
bool valid = true;
int i = 0;
do{//判断字符串是否结束了
charc = input[i];
if (!isalnum(c)) {
valid = false;
break;
}
i++;
} while (input[i] != '\0');//判断字符串是否结束了
if (!valid)
invalid_vec.push_back(input);
else
valid_vec.push_back(input);
} while (input[0] != '\0');//判断输入是否是空行,如果是,就结束了
// 去重valid_vec存储去重后的
set<string>st(valid_vec.begin(), valid_vec.end());
valid_vec.assign(st.begin(), st.end());
//输出去重后的合法字符串
int nums_valid = valid_vec.size();
for (int i = 0; i < nums_valid-1; i++)
{
cout << valid_vec[i] << " ";
}
cout << valid_vec[nums_valid - 1]<<endl;
//输出非法字符串
int nums_invalid = invalid_vec.size();
for (int i = 0; i < nums_invalid - 1; i++)
{
cout << invalid_vec[i] << " ";
}
cout << invalid_vec[nums_invalid - 1] << endl;
//输出左移10位的
nums_valid = valid_vec.size();
for (int i = 0; i < nums_valid - 1; i++)
{
int remove = 10 % valid_vec[i].length();
rotate(valid_vec[i].begin(), valid_vec[i].begin()+ remove, valid_vec[i].end());
cout << valid_vec[i] << " ";
}
rotate(valid_vec[nums_valid - 1].begin(), valid_vec[nums_valid - 1].begin() + 10 % valid_vec[nums_valid - 1].length(), valid_vec[nums_valid - 1].end());
cout << valid_vec[nums_valid - 1] << endl;
//输出左移然后排序之后的
sort(valid_vec.begin(), valid_vec.end());
for (int i = 0; i < nums_valid - 1; i++)
{
int remove = 10 % valid_vec[i].length();
rotate(valid_vec[i].begin(), valid_vec[i].begin() + remove, valid_vec[i].end());
cout << valid_vec[i] << " ";
}
rotate(valid_vec[nums_valid - 1].begin(), valid_vec[nums_valid - 1].begin() + 10 % valid_vec[nums_valid - 1].length(), valid_vec[nums_valid - 1].end());
cout << valid_vec[nums_valid - 1] << endl;
return 0;
}