刷题当中遇到的一些编程技巧
1.如何获得一个二维数组的行数和列数;
int m=matrix.size(),n=matrix[0].size();
2.记住 在一个二维数组当中,第一步是判断数组是否为空
int m=matrix.size(); //取出行的数目
if(m==0) return false; //如果行0 ,说明是个空数组,不为0,接下来才是取列数
int n=matrix[0].size(); //取出多少列
另外一种判空的方法是 推荐使用第二种
if(matrix.empty()||matrix[0].empty()) return false;
3.二分法的常用套路
在进行二分的时候,左右两边的边界值可以取以下两种
int left=0;int right=vector.size()-1;
或者
int begin=0 ;int right=vector.size()-1;
在取中间值的时候,主因以下两种格式
int mid=left+((right-left)>>1); //移位操作更加好
//int mid=(left+right)/2 尽量不要用这种
接下来就是重要的循环体 了
方法1
while(left<=right) //直到边界范围内没有数值 那么这样你就要用一种方法使得能够使得左右范围交叉
//那么使用的方法就是以下结构
{
int mid=left+((right-left)>>1);
if( 中间值 > target ) right=mid-1;
else if( 中间值 < target) left=mid+1;
else return true;
}
return false; //当没有一个相等值,那么所有边界就会不断的加减,以至于边界交叉->跳出->返回错误
4.当你想返回一个临时的 向量
这是一种初始化的思想
return vector<int>{-1,-1};
return vector<int> {};
5.分割字符串的方法
- 通过stl实现
首先了解 find 函数
原型:size_t find ( const string& str, size_t pos = 0 ) const;
功能**:查找子字符串第一次出现的位置。**
参数说明:str为子字符串,pos为初始查找位置,默认从头开始。
返回值:找到的话返回第一次出现的位置,否则返回string::npos
例如:
size_t pos = strs.find("!");
size_t pos = strs.find("!", 5) //从第5个位置开始找
同时,还有一个find_first_of(),find_last_of()不是全匹配,而find()是全匹配
其功能是:查找子串中的某个字符最先/最后出现的位置
while(pos!=string::npos) {操作字符串} npos为字符串的最后一位
其次,了解字符串和int之间的转换
int----->string
eg: string a=to_string(5);
-----------------------------------------------------------
string------->int //建议使用前两种
eg1: string b="532" ; int a=atoi(b.c_str());
eg2: string b="532" ; int a; stringstream(b)>>a;
eg3: string b="532" ; int a; sscanf(b.c_str(),"%d",&a);
了解 substr 函数
原型:string substr ( size_t pos = 0, size_t len = npos ) const;
功能:获得子字符串。
参数说明:pos为起始位置(默认为0),len为字符串长度(默认为npos)
返回值:子字符串
string x = strs.substr(0,len); //获得从0位置开始到len长度的字符串
string s("12345asdf");
string a = s.substr(0,5); //the answer is "12345"
-
还有一种使用strtok() 函数的方法 以后有时间探究
c语言中还有一种方法分割字符串:
line=GET /hello.c http.1001.1 //如何分割这三个字符串 //利用正则表达式 sscanf(line,"%[^ ]%[^ ]%[^ ]",method,path,protcol);//这样就可以把字符串分割 还有就是可以利用strtok的方法
6.字符串与字符的操作
首先对于一个字符串,你知道其长度吗?
string a = "12345";
a.length(); 输出的结果为5 a.size(); 输出的结果为5
sizeof(char) 输出的结果为1 sizeof(a) 输出的结果为28 为啥为28?
同理
string a = "12345";
char* ptr=&a[0]; //a[0]输出为1
cout << ptr<< endl; //输出为 12345
cout <<*ptr<<end; //输出为 1 将ptr向后移动5位后将指向‘\0’,也就是a[5]
此外,string还有抹除的操作
string a = "12345";
a.erase(2,1); //a="12"
a.erase(1,3) //a="15"
7.如何测试一个程序的时间
clock_t start, finish;
double totaltime;
start = clock();//墙上时间
.....程序......
finish = clock();
totaltime= (double)(finish - start) / CLOCKS_PER_SEC;每秒的滴答数
可以参考APUE210页
8.二维向量的初始化
bool 类型 其它类型类似
vector<vector<bool>> dp(一维大小);
for (int i = 0; i < dp.size(); i++) {
dp[i].resize(二维大小, true);//初始化的值 默认初始化为false
}
输出:
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
9.判断一个字符时候是数字
自己判断
if(c >='a' && c<='z' || c >='A' && c<='Z')) printf("是字母\n");
调用库函数:
if(isdigit(c) != 0) printf("是数字\n") ;
10.优先级队列(大根#小根)的设置
//数据类型为 listnode类
class mycompare { //首先设置一个比较器
public:
bool operator()(ListNode p1, ListNode p2)const {
return p1.val > p2.val; //这儿是个小根堆
}
};
//开始设置
priority_queue<ListNode,vector<ListNode>,mycompare> smallheap;
//数据类型为 int 可以直接设置
//系统默认的大根堆,其实这儿根本就不用设置小根堆,因为我们直接存相反数就可以了
priority_queue<int, vector<int>, greater<int>> small;
priority_queue<int, vector<int>, less<int>> big;
//我们知道pair类型是进行双关键字进行排序,比如pair<int,string>如果我们按照默认系统大根堆进行插入,就会是双关键字排序的结果,int和string都排序
//但是如果我们设置了以上的排序方法,那么就是有第一个关键字进行排序。
11.怎样设置vector的排序呢?
//降序排序
sort(vInts.begin(), vInts.end(),greater<int>());
//升序排序
sort(vInts.begin(), vInts.end(),less<int>());
11.大写字母变小写互相变换怎么变?
//'A'=65
//'a'=97
char a='a';
a^=32 a='A';//
12.求一个数的质数
for(int i=2;n>1;i++) //从2开始进行榨干
while(n%i==0) res+=i; //当while成立 说明i是一个n的质数。那么可以把它取出来
扩展:求一个数的约束 很简单啦 直接就一个循环
那么一个数的约数是一个奇数,那么那么这个数一定是n^2 一个平方数
13.怎样去最小公倍数呢
求ab得最小公倍数
int x=a*b/_gcd(a,b);
求abc的最小公倍数
int y=x*c/_gcd(x,c);
13.如何判断两个数的异号性
//方法一 在数据的不大的时候,可以使用相乘
//下面介绍另外一种方法
bool minus=false;
if(a<0) minus=!miuns,a=-a;
if(b<0) miuus=!minus,b=-b;
14.求最大公约数 gcd
//第一种:递归 思想 辗转相除法
int gcd(int a,int b)
{
if(b == 0) return a;
return gcd(b,a%b);
}
//第二种:非递归
int gcd(int a,int b){
while(b){
int t = b;
b = a%b;
a = t;
}
return a;
}
15.不要对 a.size()这种做加减法
//因为这种情况 size()是一个无符号整数,当和int做加减法的时候,如果产生了一个负数,就会是一个很大的数。比如-1;
16.stringstream 的应用
//函数是从一个字符串里面提取东西 比如一个sting 为“laign rui ai shang chai jin"
//我们想要提取里面的单词 就可以使用这种方法
stringstream raw(str);
vector<string> words;
string word;
while(raw>>word) words.push_back(word);
17.对于map和unordered_map不用迭代器遍历
for(auto x:map) //map<string ,int>
{
string a=x.first;
int b=x.second;
}
18.使用unordered_multiset
//unordered_multiset能够记录重复的值
unordered_multiset<int> hash;
hash.insert(1);
hash.insert(1);
//如果要进行删除 需要注意 如果直接删除就会把所有的值删除,所以我们需要找一个迭代器来一个一个的删
hash.erase(1) //两个都没有了
auto it =hash.find(1);
hash,erase(it) //只删除了一个
19.vector用迭代器删除的问题(腾讯问过这种问题)
在利用iter进行删除的时候,比如 vector<int> st;
for(auto itr=st.begin();itr!=st.end();itr++){
st.erase(itr); XXXX //这种方法是不可取的,因为itr都被删除了,就不能继续使用了
//正确做法:
itr=st.erase(itr);
//也可以使用(自增、自减)
st.erase(itr++)
}
如果vector中存储的元素是指针,那么erase()或者clear()并不会删除指针指向的对象或者内存空间,要小心内存泄漏问题。可以先删除指针指向的内容,然后在删除vector中的元素。如下:
for(.....)
{
delete(*itr);
(*ter)==NULL;
}
20. C++ 上取整和下取整的转换
//C++没有上取整的操作 那么要求a/b的上取整可以写成 (a+b-1)/b;
21. 如果使用一些容器的东西 不想处理边界值,可以在两边加上哨兵
22.如何去替代我们的goto语句
在编程中,我们一般都不允许使用goto语句,但是我们就可以使用do-while(0)替代;
do{
....
break;
.....
}while(0)