Leetcode 4.16

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;
}
相关推荐
Yingye Zhu(HPXXZYY)1 天前
ICPC 2023 Nanjing R L 题 Elevator
算法
阿维的博客日记1 天前
LeetCode 139. 单词拆分 - 动态规划解法详解
leetcode·动态规划·代理模式
程序员Xu1 天前
【LeetCode热题100道笔记】二叉树的右视图
笔记·算法·leetcode
笑脸惹桃花1 天前
50系显卡训练深度学习YOLO等算法报错的解决方法
深度学习·算法·yolo·torch·cuda
阿维的博客日记1 天前
LeetCode 48 - 旋转图像算法详解(全网最优雅的Java算法
算法·leetcode
GEO_YScsn1 天前
Rust 的生命周期与借用检查:安全性深度保障的基石
网络·算法
程序员Xu1 天前
【LeetCode热题100道笔记】二叉搜索树中第 K 小的元素
笔记·算法·leetcode
THMAIL1 天前
机器学习从入门到精通 - 数据预处理实战秘籍:清洗、转换与特征工程入门
人工智能·python·算法·机器学习·数据挖掘·逻辑回归
Kevinhbr1 天前
CSP-J/S IS COMING
数据结构·c++·算法
蕓晨1 天前
set的插入和pair的用法
c++·算法