LeetCode做题小结

一、小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 20x0+21x1+...+2nxn得到,但注意无符号整数类型和有符号整数类型的判断,不考虑的话直接采用第二种方法可能会导致溢出。

// 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. 双指针的使用

如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法。

  1. https://leetcode.cn/problems/kLl5u1/ 一个排好序的数组,找到两个数之和为target的那两个数;
  2. https://leetcode.cn/problems/1fGaJU/ 以及找数组中所有三个数之和为0的数,此处只需固定第一个数,第二、三层循环并行进行,当然数组要先排序。

另外以下情况也可以使用双指针

  1. 最大序列和 https://www.nowcoder.com/practice/df219d60a7af4171a981ef56bd597f7b?tpId=40设置双指针,当发现序列和小于0就不断移动首指针直到序列和大于等于0
  2. 再比如需要连续的一段数列,发现满足某个条件后,可以省略中间不需要的值,比如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

  1. 如果要先对一个指标进行排序,在第一个指标的基础上再对第二个指标进行排序,比如先对成绩排序,成绩相同的则按学号进行排序,可以如下定义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);
  1. 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的因数
最大公约数,最小公倍数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值