2022.02.04 Day1
前言
为日后的算法面试做准备,自己也很喜欢算法这个东西,每天3~5道题。
刷题
1.leetcode 209 长度最下的子数组
题目
长度最下的子数组
大致的意思是从数组中找到长度最小的数组,并且数组内的和是大于等于给定的数target的
思路
最基本的思路当然是双重遍历,时间复杂度是O(N2),但是本题的数据大小为105,所以这是肯定过不掉的,所以我们需要优化。
我们可以发现的是,对于满足条件的某个区间,区间左右端点分别i与j,其中i表示最接近j的那个数的下标,当j向右移动的时候,i也会向右移动或者原地不动。所以我们可以用双指针来优化这个到O(N)。
代码
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int res = INT_MAX;
//每次找的是能处于最左边的数
for(int i = 0, j = 0,sum_ = 0; j < nums.size();++j){
sum_ += nums[j];
while(sum_ - nums[i] >= target) sum_ -= nums[i++];
if(sum_ >= target)res = min(res, j - i + 1);
}
/*对于每个nums[j]找到的nums[i]是离nums[j]最近的那个满足sum_ >= target的数
每次这样维护是最小的
*/
if(res == INT_MAX) res = 0;
return res;
}
};
2.leetcode 208 实现Trie(前缀树)
题目
思路
就是Trie的模板题,我习惯用数组来模拟Trie树,所以打个板子题就好了,要用个check数组来维护一下最后一个数即可,大概把数据范围定在在8e4以上就可以过了。不过实测发现8e4跟1e5的运行速度不一样,后者会快个20多ms,可能是因为在解析8e4的时候会慢一点?
然后有个细节是,用bool类型的check数组,因为bool的大小是1个字节,会相对于int小一点,在内存上会更加占优。
代码
const int N = 1e5;
int son[N][26], idx = 0;
bool check[N];
class Trie {
public:
Trie() {
memset(son, 0 ,sizeof(son));
memset(check, 0 ,sizeof(check));
}
void insert(string word) {
int pos = 0;
for(int i = 0; word[i]; ++ i){
int temp = word[i] - 'a';
if(!son[pos][temp]) son[pos][temp] = ++idx;
pos = son[pos][temp];
//check[pos] = 1;
}
check[pos] = 1;
}
bool search(string word) {
int pos = 0;
for(int i = 0; word[i]; ++ i){
int temp = word[i] - 'a';
if(!son[pos][temp]) return false;
pos = son[pos][temp];
}
if(check[pos]) return true;
else return false;
}
bool startsWith(string prefix) {
int pos = 0,temp;
for(int i = 0; prefix[i]; ++ i){
temp = prefix[i] - 'a';
if(!son[pos][temp]) return false;
pos = son[pos][temp];
}
return true;
}
};
/**
* Your Trie object will be instantiated and called as such:
* Trie* obj = new Trie();
* obj->insert(word);
* bool param_2 = obj->search(word);
* bool param_3 = obj->startsWith(prefix);
*/
3.leetcode 201 数字范围按位与
题目
思路
对于left 和 right 我们会发现二进制表示中的两个数从左到右第一个不相等的数的后面按位与起来的后都是0.
也就是left可能是XXX0YYY,right可能是XXX1ZZZ,这是由于left小于right,我们还能发现XXX1000与XXX0111肯定都在left与right的范围内,所以从第一个不相同的位向后与都是0.即答案是XXX0000。
代码
class Solution {
public:
int rangeBitwiseAnd(int left, int right) {
int res = 0;
for(int i = 30; i >= 0; --i){
if((left >> i & 1) != (right >> i & 1)) {//lowbit操作
res = res << i + 1;
break;
}
else{
res = (res << 1) + (left >> i & 1);
}
}
return res;
}
};
注意点是lowbit操作一定要与上1,否则将一个数向左或者向右移动i位的话,得到的结果只会是移位后的结果。

浙公网安备 33010602011771号