1.找两个和为目标值且不重叠的子数组
找两个和为目标值且不重叠的子数组
初始化变量:
- sum:用于存储当前左边界 l 到右边界 r 之间的子数组和。
- r:初始化为数组的最后一个元素的索引,表示初始的右边界。
- ans:用于存储最小的两个子数组长度和,初始化为一个较大的数(2e5),确保后面能找到更小的值来更新它。
- len:一个数组,用于存储从当前位置到数组末尾的子数组的最小长度。其初始值都设为 2e5。
滑动窗口遍历数组:
- 外部循环从右向左遍历数组,l 表示当前子数组的左边界。
- 在每次外部循环中,sum 从 l 开始累加元素,直到 sum 大于 target。
- 如果 sum 大于 target,则通过减少右边界 r 的元素来缩小子数组的范围,直到 sum 再次小于或等于 target。
检查当前子数组和:
- 如果 sum 等于 target,则找到了一个和为 target 的子数组。 计算当前子数组的长度 curlen,它是 r - l +1。
- 更新 ans 为 ans 和 curlen + len[r + 1] 中的较小值。这里 len[r + 1] 表示从 r + 1到数组末尾的子数组的最小长度。因为我们想找到两个不相交的子数组,所以加上从 r + 1 开始的子数组的最小长度是合理的。
- 更新len[l] 为 curlen 和 len[l + 1] 中的较小值。这是因为从 l 开始到数组末尾的子数组的最小长度要么是当前子数组的长度,要么是从 l + 1 开始到数组末尾的子数组的最小长度。
返回结果:
- 如果找到了两个符合条件的子数组,则返回 ans。
- 否则,返回 -1,表示没有找到这样的子数组。
这段代码的关键点在于使用了滑动窗口和动态规划的思想。通过维护一个 len 数组来记录从当前位置到数组末尾的子数组的最小长度,避免了重复计算。
cpp
class Solution {
public:
int minSumOfLengths(vector<int>& arr, int target) {
//从右往左遍历
//用l和r指针控制位置,选择不相交区域
int r = arr.size() - 1; int l = r;
//用vector<int>保存当前位置等于target的最小子数组长度
//加一是因为需要比对r+1的值
vector<int> len(arr.size() + 1, 2e5);
//ans保存两个最短子数组长度和
int ans = 2e5;
//保留l到r位置的和
int sum = 0;
for (; l >= 0; l--) {
sum += arr[l];
//和超出target了,将指针向右移动
while (sum > target) {
sum -= arr[r];
r--;
}
if (sum == target) {
//从右向左,在当前位置的子串最小值
len[l] = min(len[l + 1], r - l + 1);
//更新最终的两个子数组和,注意len[r + 1]
ans = min(ans, r - l + 1 + len[r + 1]);
} else {
len[l] = len[l + 1];
}
}
return ans == 2e5 ? -1 : ans;
}
};
2.Protocol buffer 编码和解码 谷歌 整数变长编码
https://www.cnblogs.com/love-study-chase/p/13443062.html
cpp
#include <iostream>
#include <unordered_map>
#include <string>
#include <cstring>
#include <iomanip>
using namespace std;
void encode(unsigned int n){
if(n < 128) {
if(n < 16) cout <<"0X0"<<hex<<n;
else cout <<"0X"<<hex<<n;
return;
}
while(n){
unsigned int tmp;
if(n >= 128){
tmp = (0x80 | (n & 0x7F));
cout<<"0X"<<setiosflags(ios::uppercase)<<hex<<tmp;//大写16进制数字
}else{
tmp = (0x00|(n & 0x7F));
if(tmp < 16) cout <<"0X0"<<hex<<tmp;
else cout <<"0X"<<hex<<tmp;
}
n >>= 7;
}
return;
}
unsigned int decode(string& x){
unsigned int u, res = 0;
int cnt = 0;
while(x.size()){
string tmp = x.substr(0,4);
//必须要依据格式输入 否则超索引范围
x = x.substr(4);
tmp = tmp.substr(2);
u = 0;
for(int i = 0; i < tmp.size(); i++){
if(tmp[i] >='0' && tmp[i] <= '9') u = u * 16 + tmp[i] - '0';
if(tmp[i] >='A' && tmp[i] <= 'F') u = u * 16 + tmp[i] - 'A' + 10;
}
unsigned int temp;
temp = (u & 0x7F);
for(int i = 1; i <= cnt; i++){
temp <<= 7;
}
res += temp;
cnt++;
}
return res;
}
int main(){
unsigned int n;
string x;
cin >> n >> x;
encode(n);
cout <<endl;
cout <<dec<<decode(x)<<endl;
return 0;
}