文章目录
一、小tips
1. 移位运算的运用
1. 将二进制转化为十进制
通过移位得到结果,另外一种方法是采用 2 0 ⋅ x 0 + 2 1 ⋅ x 1 + . . . + 2 n ⋅ x n 2^0\cdot x_0+2^1\cdot x_1+...+2^n\cdot x_n 20⋅x0+21⋅x1+...+2n⋅xn得到,但注意无符号整数类型和有符号整数类型的判断,不考虑的话直接采用第二种方法可能会导致溢出。
// number[i]存储第i位的数值(从地位开始计算,即number[0]的权值为1,number[1]的权值为2,依次类推
for (int i = 0; i < 32; ++i) {
//res += number[i] * pow(2, i); 这样可能会产生上溢出
res = res | (number[i] << i);
}
2. 乘以2除以2的计算
直接用移位运算即可
2. 双指针的使用
如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法。
如
- https://leetcode.cn/problems/kLl5u1/ 一个排好序的数组,找到两个数之和为target的那两个数;
- https://leetcode.cn/problems/1fGaJU/ 以及找数组中所有三个数之和为0的数,此处只需固定第一个数,第二、三层循环并行进行,当然数组要先排序。
另外以下情况也可以使用双指针
- 最大序列和 https://www.nowcoder.com/practice/df219d60a7af4171a981ef56bd597f7b?tpId=40设置双指针,当发现序列和小于0就不断移动首指针直到序列和大于等于0
- 再比如需要连续的一段数列,发现满足某个条件后,可以省略中间不需要的值,比如a1,a2,a3,…,an,已知a1+…+a(s-1)<k,但a1+…+as>=k,可能由于ak过大,故可以减小首指针,直到aq+…+as>=k,a(q+1)+…+as<k,此处则直接置首指针为q+1,因为求的是最小面积,故若首指针为1-q中的值,而尾指针为s且尾指针后面会自增,则和一定包含aq+…+as,故一定会大于k,长度明显大于s-q+1
故此处可以使用双指针,此题参见https://www.nowcoder.com/practice/8ef506fbab2742809564e1a288358554?tpId=40
q = 0;
sum = 0;
len = INT_MAX;
for (int p = 1; p <= m; ++p) {
sum += column[p];
// cout << "p:" << p << " q:" << q << " sum:" << sum << endl;
// 用while不用if:省略掉了最开始的q和到了临界值的q中间的那些值,比如a1,a2,a3,..,an
// 已知a1+...+a(s-1)<k,但a1+...+as>=k,可能由于ak过大,故可以减小首指针,
// 直到aq+...+as>=k,a(q+1)+...+as<k,此处则直接置首指针为q+1,因为求的是最小面积,故
// 若首指针为1-q中的值,而尾指针为s且尾指针后面会自增,则和一定包含aq+...+as,故一定会大于k,长度明显大于s-q+1
while (sum >= k) {
len = min(len, p - q + 1);
sum -= column[q++];
}
if (len != INT_MAX) {
res = min(res, (j - i + 1) * len);
}
}
3. int和double的较大值
int为0x3f,double为0x43,注意要用memset
而不能直接赋值
double tmp;
memset(&tmp, 0x43, sizeof(tmp));
cout << "memset tmp:" << tmp << endl;
tmp = 0x43;
cout << "tmp:" << tmp << endl;
int a;
memset(&a, 0x3f, sizeof(a));
cout << "memset a:" << a << endl;
a = 0x3f;
cout << "a:" << a << endl;
结果:
memset tmp:1.0844e+16
tmp:67 // 0x43为整数,变成十进制为67,再自动类型提升为double就为67
memset a:1061109567
a:63
二、 提高代码效率
注意if else语句中判断条件的顺序,发生情况多的在前面先判断。
三、操作注意事项
1. vector清空
清空有两种方法,一种是clear
,一种是和空vector进行swap
,其中,clear
清除元素但不回收内存,而swap
清除元素并回收内存。
vector<int> v;
v.push_back(2);
v.push_back(3);
v.clear();
cout << "size:" << v.size() << " capacity:" << v.capacity() << endl;
v.push_back(2);
v.push_back(3);
vector<int>().swap(v);
cout << "size:" << v.size() << " capacity:" << v.capacity() << endl;
输出:
size:0 capacity:2
size:0 capacity:0
另外,若此次清空下次还需要添加元素的话,用clear
更快一些
vector<int> v;
double start, end;
start = clock();
for (int i = 0; i < 100000; ++i) {
v.push_back(1);
v.clear();
}
end = clock();
cout << end - start << endl;
start = clock();
for (int i = 0; i < 100000; ++i) {
v.push_back(1);
vector<int>().swap(v);
}
end = clock();
cout << end - start << endl;
输出:
29
149
另外,即使不增加元素只是不断地清空,clear
也更快一些,将上面代码的两行push_back
注释掉,得到的输出如下:
11
77
2. stl中的sort
- 如果要先对一个指标进行排序,在第一个指标的基础上再对第二个指标进行排序,比如先对成绩排序,成绩相同的则按学号进行排序,可以如下定义
cmp
函数:
bool cmp(const struct student& s1, const struct student& s2) {
if (s1.score < s2.score) {
return true;
}
else if (s1.score == s2.score && s1.id < s2.id) {
return true;
}
else {
return false;
}
}
另外对于sort函数,第二个参数是最后要排序的元素的后一个地址,如:
sort(vec.begin(), vec.end());
// 数组的长度是n
sort(array, array + n);
- 对
vector<pair<int, int>>
进行排序cmp函数中不能含有<=或者>=,否则报错Expression :Invalid comparator
,对于vector<int>
型却可以使用<=或者>=
另外需要注明的是:pair 默认对first升序,当first相同时对second升序;
错误写法:
vector<pair<int, int>> vec2 = { {1,4},{9,3},{1,2},{6,6} };
sort(vec2.begin(), vec2.end(), [](const pair<int, int>& a, const pair<int, int>& b) {return a.first <= b.first; });
// 注意,这种写法等价于<=,也会报错
sort(vec2.begin(), vec2.end(), [](const pair<int, int>& a, const pair<int, int>& b) {if (a.first != b.first) return a.first < b.first; else return true; });
正确写法:
vector<int> vec = { 5,2,9,6,3 };
sort(vec.begin(), vec.end(), [](const int& a, const int& b) {return a <= b; });
cout << "vec after sorted:";
for (auto v : vec) {
cout << v << ' ';
}
cout << endl;
vector<pair<int, int>> vec2 = { {1,4},{9,3},{1,2},{6,6} };
sort(vec2.begin(), vec2.end(), [](const pair<int, int>& a, const pair<int, int>& b) {return a.first < b.first; });
cout << "vec2 after sorted:";
for (auto v : vec2) {
cout << v.first << ' ' << v.second << " ";
}
cout << endl;
输出:
vec after sorted:2 3 5 6 9
vec2 after sorted:1 4 1 2 6 6 9 3
3.memset
原型为
void *memset(void *s, int v, size_t n);
注意第三个参数为size_t
类型,如len*sizeof(int)
四、其他
1. 数组
1. 数组初始化为零
一个方法是直接声明为全局变量,另一个方法是int sum[100]={0};
2. 传递二维数组参数
可以以int (*parr)[4]
的形式传递,之前我直接用int**
不行
2. 平年闰年
平年365,闰年366天,平年的2月28天,闰年的2月有29天
判断:年份为整百数时,能够整除400,则为闰年;不为整百数时,能够整除4,则为闰年。
3. ASCII码表
48-57 : 0-9
65-90 : A-Z
97-122 : a-z
4. 质数合数因数
质数:又叫素数,是一个大于1的自然数,除了1和它自身以外不含有其他因数
合数:是一个大于1的自然数,除了1和它自身以外含有其他因数
因数:又叫约数,若a*b=c,则a和b都是c的因数
最大公约数,最小公倍数