Skip to content

Latest commit

 

History

History
291 lines (183 loc) · 8.85 KB

0.1 C++_tips.md

File metadata and controls

291 lines (183 loc) · 8.85 KB

[TOC]

TRAILS

什么时候再括号里加限制条件,什么时候在for循环体内加限制条件

这两者的区别在哪 括号里的是必须条件,不满足条件直接结束函数

定义类时不要忘记最后的分号!养成写public和private的习惯!!!!!
class xxx{

}; //!!!!!!!!!!!!!!!!!!!
确定每个变量的定义位置合适,避免出现重复定义:2. 两数相加
for循环每个部分之间用分号;分隔
C语言中列举数组元素使用花括号{} []是在python中对list初始化的符号
path.pop_back()里面不放任何元素
从字符串string中截取下标[startIndex,i]的子串
string word = s.substr(startIndex,i-startIdex+1);
// 第一个参数代表起始位置,包含起始位置本身
//第二个参数代表从起始位置开始数多少位元素
初始化一个容器的时间复杂度

如果容器里没有元素的初始化,O(1)

如果容器内有元素,O(n),因为实际的初始化过程都是拷贝的过程

定义二维数组的方式
vector<vector<int>> dp(m,vector<int>(n,0));
vector<vector<int>> buckets(k+1); //只定义第一层长度
对数组进行排序
sort(nums.begin(),nums.end());
vector 取最后一位元素
vector.back();
vector.front();
//vector支持.front() 但是不支持pop_front()
unordered_set

==顺序容器没有find方法?只有关联容器有吗?关联容器为什么要提供这种方法?为什么顺序容器又不提供?==

==关联容器中key的顺序与插入顺序并不一致==

unordered_set.find(x) 查找x在set中是否存在,不存在返回尾迭代器,存在呢?返回第一个key为x的迭代器 find时间复杂度  查询效率O(1) 增删效率O(1) 
unordered_set.insert(x) 插入x 返回一个pair,其第一个元素是指向刚插入元素的迭代器,第二个元素是bool类型,若插入成功(对应容器中不存在key),返回true;若插入失败(对应容器中已存在key),返回false。
unordered_set.erase(x) 删除x 返回删除的最后一个元素的下一个元素的迭代器。

==为什么unordered_set的查询和增删效率这么高?==

https://blog.csdn.net/fjhugjkdsd/article/details/108091424

底层结构使用一个哈希函数 hash(key) = position 将key与元素存储位置建立一个映射

因此在查找,增删时,我=都只需要调用hash(key),即可知道该元素(或即将被存储的)的存储位置

如何由数组直接构造一个unordered_set

利用vector的一对迭代器即可构造unordered_set

unordered_set<string> wordSet(wordDict.begin(),wordDict.end());
int能表示的数字:2开头的10位10进制数字

signed int能够表示的数据范围:-2147483648~2147483647

如何倒序一个vector,其时间复杂度为?
如何根据index范围生成vector的子数组?如何生成子字符串?

利用迭代器范围构造

vector<int> left(postorder.begin(),postorder.begin() + border);

与生成子字符串进行对比,==字符串是否可以用上面的方法?==

string word = s.substr(startIndex,i-startIdex+1);
// 第一个参数代表起始位置,包含起始位置本身
//第二个参数代表从起始位置开始数多少位元素
ListNode
  1. 写一个ListNode

要求:两个成员变量,val和next,构造函数

class ListNode{
public:   
    int val;
    ListNode *next;
    ListNode(int val=0,ListNode *next = nullptr):val(val),next(next){}  
};
//简单的把public理解为让任何人可以使用的方法,即接口函数;而private为不想让别人使用的内部细节

ListNode *head = &ListNode(val);

不可以,构造函数创造临时变量,并未给其分配内存地址

正确的做法是:

ListNode *head = new ListNode(val);

但是这样的话,谁来负责销毁这个node呢?

其实对于本题来说,销毁链表本事就可以了

这样可以吗?

ListNode node = ListNode(val);

ListNode *head = &node;

取dp数组最大值的操作完全可以在计算dp数组时使用: 300. 最长递增子序列
当需要通过if进行下标检查来保证index有意义时,记住下标检查的表达式一定要放在最前侧:300. 最长递增子序列
当某个数组的大小可能为0时,使用其长度构建另一个数组是危险的:188. 买卖股票的最佳时机iv
string在尾部插入和删除元素,可以用vector的push_back和pop_back,有自己的方法吗?

在尾部插入可以使用重载的运算符 “+=”

string path;
path +="hello";
path +=" ";
path +="world"
当遍历某数组,最后一个数的操作与其他位置不同时,例如构造ip地址"0.0.0.0"或构造路径字符串”1->2->3“,注意循环变量要在for循环外部定义使得外部能够访问到:257. 二叉树的所有路径
string与int数值转换
string to_string()
int stoi(int) //将字符串转换为int类型,注意这里类型需要匹配
慎用nums.size()-1!:34. 在排序数组中寻找target的下界和上界

还没全部验证,最起码在string和vector中,使用size()函数返回的是其容器内自定义的类型string::size_typevector<int>::size_type 它是一个无符号类型整数

当我们将无符号类型与有符号类型进行运算时, 编译器会自动将所有数据全部看做无符号类型的数字。

int,short,long,long long默认都是有符号整型。

unsigned a = 0;
unsigned b = a-1;  //b为4294967295
int c = a-1;	//c为-1

在上面的例子中,a-1是无符号运算,得到4294967295(4字节全1),因此b也为4294967295,但是c是有符号类型,对于int类型,全1表示的正是-1。

因此,我们发现,当数组为空数组时,单独地使用nums.size()-1是危险的,因为我们潜意识里将这个表达式等同于-1来使用。

给我们的启示:

  • 当单独使用nums.size()-1时,确保其一定不为空数组。在可以的情况下,使用<nums.size()而避免使用<=nums.size()-1
  • 或者避免单独使用nums.size()-1,使用一个int型变量来代替数组的大小
int size = nums.size(); //使用int类型表示数组长度是安全的

for(int i=0;i<size-1;i++){  
	
}

==以前特别经常使用nums.size()-1,尤其是在for循环中,也没办法一一排查了,后面写代码的时候注意==

#if 0 
#endif
用于注释块状代码
~  &  |  ^  位反 位与 位或 位异或
! && ||     逻辑非 逻辑与 逻辑或
C++ 没有内置乘方运算符
pow(2,a); //表示2的a次方,顺序不可颠倒,注意返回值是double的,类型转
三元条件运算符使用的注意事项

三元条件运算符可以用做左值,也可以用作右值,这取决与你。格式如下:

eg.
maxLen = maxLen>ap? maxLen:ap;
  1. 三元条件运算符的优先级很低,因此使用时最好加上括号,以避免不必要的麻烦。
  2. 虽然它能提高我们的代码简洁度,但最好不要嵌套两层以上,这会给阅读造成极大的压力。
  3. 我们在:两侧不能使用列表构造的方式对vector进行值传递
vector<int> point= {0,1};
point = point[1]>(j-i+1)? point:{i,j-i+1}; //compile error!

它的一个常用场景是更新极值,当然,还有另一种方式更加的容易理解,即使用max(),min()函数。

min() and max()
  1. 两个用于比较的实参需要的拥有相同的类型
int right = min(i+k-1,s.size()-1);
//由于s.size()的返回类型为string:size_type而并不是int
//因此编译错误

之所以需要是相同的类型,是因为min和max的泛型算法定义中仅使用了一个泛型T,而并没有使用两个。

template<class T> const T& min(const T& a, const T& b);

template<class T, class Compare>
const T& min(const T& a, const T& b, Compare comp);

template<class T> const T& max(const T& a, const T& b);

template<class T, class Compare>
const T& max(const T& a, const T& b, Compare comp);

至于为什么不使用两个类型,而非要规定一个类型,原因在这里有详细的分析:https://stackoverflow.com/questions/56725358/why-c-compiler-gives-error-when-using-stdmax-function-for-two-different

  1. 可以用于比较多个值的大小,只需要将几个实参用{}括起来即可。
template< class T >
T min( std::initializer_list<T> ilist );

template< class T >
constexpr T min( std::initializer_list<T> ilist );

template< class T, class Compare >
T min( std::initializer_list<T> ilist, Compare comp );

template< class T, class Compare >
constexpr T min( std::initializer_list<T> ilist, Compare comp );
  1. min和max实际上属于泛型算法,在使用时需要包含头文件<algorithm>
常用ascii码值