【算法】滑动窗口(续)

news2024/11/27 8:35:30

一、将x减到0的最小操作数

1658. 将 x 减到 0 的最小操作数 - 力扣(LeetCode)

给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。

示例 1:

输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。

示例 2:

输入:nums = [5,6,7,8,9], x = 4
输出:-1

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

提示:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^4
  • 1 <= x <= 10^9

 方法一:暴力枚举法。这道题直接用暴力法还不好做,因为情况太多了,可能能左边一个右边一个,也可能左边多个右边多个,也可能左边没有右边多个,也可能左边多个右边没有。

所以直接上手这道题代码非常不好写,当我们遇到正着想难以解决时,就可以考虑反着来思考。

题目的意思可以转化为:从中间部分找到最长的一片区域使其和等于nums数组中元素所有的和减去x。如果能找到这片区域就返回最长的,如果没有找到这片区域就返回-1。

根据转换后的意思,我们可以上手暴力解法,分析如下(以示例1为例):

代码实现(C++,时间复杂度O(N^2)):

//方法一:暴力枚举法
class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n = nums.size();//数组元素个数
        int len = -1;//记录子串中满足条件的最大长度

        int arrSum = 0; //记录数组中所有元素的和
        for(auto e: nums)
            arrSum+=e;
        int target = arrSum - x; //目标值
        if(target < 0)
            return -1;
        
        if(target == 0) //如果target为0,那么就说明要移除数组的全部元素
            return n;

        for(int left = 0; left < n; ++left)
        {
            int sum = 0;//记录left到right之间的元素的和
            for(int right=left;right<n;++right)
            {
                sum+=nums[right];
                if(sum == target)
                    len = max(len, right-left+1);
            }
        }
        return len == -1 ? -1 : n - len ;
    }
};

 运行结果:

可见当数据量过多时用暴力解法就会超时。

所以我们要进行优化,我们的优化是在暴力解法的基础上进行的,分析如下:

代码实现(C++,时间复杂度O(N)): 

//方法二:滑动指针
class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int n =nums.size(),len = -1;
        int arrSum = 0; //记录数组所有元素的和
        for(auto e : nums)
            arrSum += e;
        int target = arrSum - x;

        if(target < 0) //特殊情况单独处理
            return -1;
        
        int sum = 0;//记录left到right之间所有元素的和
        for(int left = 0,right = 0;right < n; ++right) //最终结束条件是right==n
        {
            sum+=nums[right]; //入窗口
            while(sum > target)  //判断
                sum -= nums[left++]; //出窗口

            if(sum == target) //满足条件就更新len
                len = max(len,right-left+1);
        }

        return len == -1 ? -1 : n-len;
    }
};

代码中虽然是两层循环,但是结合实例,我们的left指针和right指针都是不回退的,两者最多都往后移动n次,因此时间复杂度是O(N)。相比于暴力解法,这种优化的方法效率更高。  

二、水果成篮

904. 水果成篮 - 力扣(LeetCode)

你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:

  • 你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
  • 你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
  • 一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。

给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。

示例 1:

输入:fruits = [1,2,1]
输出:3
解释:可以采摘全部 3 棵树。

示例 2:

输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。

示例 3:

输入:fruits = [1,2,3,2,2]
输出:4
解释:可以采摘 [2,3,2,2] 这四棵树。
如果从第一棵树开始采摘,则只能采摘 [1,2] 这两棵树。

示例 4:

输入:fruits = [3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:可以采摘 [1,2,1,1,2] 这五棵树。

提示:

  • 1 <= fruits.length <= 10^5
  • 0 <= fruits[i] < fruits.length

初看这道题目时,可能不好理解,我以示例4为例解释一下:

这个问题的本质就是:在数组中找出一个最长的子数组的长度,要求子数组中的水果种类不能超过两种。

方法一:暴力枚举法。暴力枚举的过程就如上面解释示例4的过程差不多,在暴力枚举的过程中需要统计水果的种类,用来控制停下的条件,统计水果的种类就需要借助哈希表,遇到一个新品种就加入到哈希表中,如果哈希表中的元素个数大于2,就停止,然后枚举下一种情况,依次进行...。

代码实现(C++,时间复杂度O(N^2)):

//方法一:暴力枚举法
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int n = fruits.size();
        int ret = 0; //记录收集水果最大数目 
        for(int left = 0;left<n;++left)
        {
            unordered_map<int,int> hash; //统计水果种类,以及该种类出现的个数
            for(int right=left;right<n;++right)
            {
                hash[fruits[right]]++;
                if(hash.size() > 2) //水果种类大于2
                    break;
                ret = max(ret,right-left+1); //如果水果种类小于2,就更新ret
            }
        }
        return ret;
    }
};

运行结果:

当数据量过大时,暴力解法就会超时。

所以我们需要对其进行优化,分析如下:

代码实现(C++,时间复杂度O(N)):

//方法二:滑动指针
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        unordered_map<int ,int>hash; //用来记录水果的种类以及对应的水果数
        int n = fruits.size();//数组中元素个数
        int ret = 0; //收集水果最大数

        for(int left=0,right=0;right<n;++right)
        {   
            //入窗口
            hash[fruits[right]]++; 
            //判断
            while(hash.size() > 2)
            {   
                //出窗口
                hash[fruits[left]]--; 
                if(hash[fruits[left]] == 0) //表示该种类的水果个数已经为0了,就需要从哈希表中删除该水果
                    hash.erase(fruits[left]);

                ++left; //更新left
            }

            //当水果种类小于等于2时更新ret
            ret = max(ret,right-left+1);
        }
        return ret;
    }
};

因为对hash进行频繁插入和删除, 这种操作是比较耗时的。所以我们可以稍微优化一下,用数组来模拟哈希表:

//方法二:滑动指针
class Solution {
public:
    int totalFruit(vector<int>& fruits) {

        int hash[100001] = {0};//根据题目,最多有10^5个水果,所以直接开一个大一点的数组,包含所有情况
        int n = fruits.size();//数组中元素个数
        int ret = 0; //收集水果最大数
        int kinds = 0;//表示窗口内一种有多少种水果

        for(int left=0,right=0;right<n;++right)
        {   
            if(hash[fruits[right]] == 0)
                ++kinds; //维护水果种类
            //入窗口
            hash[fruits[right]]++; 
            //判断
            while(kinds > 2)
            {   
                //出窗口
                hash[fruits[left]]--; 
                if(hash[fruits[left]] == 0) 
                    --kinds;

                ++left; //更新left
            }

            //当水果种类小于等于2时更新ret
            ret = max(ret,right-left+1);
        }
        return ret;
    }
};

 三、找到字符串中所有字母异位词

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

示例 1:

输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。

 示例 2:

输入: s = "abab", p = "ab"
输出: [0,1,2]
解释:
起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。
起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。
起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。

提示:

  • 1 <= s.length, p.length <= 3 * 10^4
  • s 和 p 仅包含小写字母

先来解释一下题目的意思(以示例1为例):

明白题意后,先考虑一个问题,给定两个字符串,如何判断它们两个是异位词?

法一:将这两个字符串按字典序先排序,然后用两个指针,分别指向这两个字符串的起始位置,遍历过程中依次比较,若每个位置都相等,那么它们两个字符串就是异位词。

法二:记录字符串1中的字符以及它出现的次数,再记录字符串2中的字符以及它出现的次数, 可以用哈希表记录字符以及出现的次数。若两个哈希表相等,那么它们两个字符串就是异位词。

法二是更方便的。

据此,我们的暴力解法就来了,先用哈希表1来存储p中每个字符出现的次数,接着记录p中字符串的长度m,在s中暴力找出所有长度为m的子串,用哈希表2来依次存储这些子串,当存储第一个时,就和哈希表1进行比较,若相等,将这个子串在s中的起始位置的下标存放到一个容器中。接着哈希表2再来存储下一个子串,再比较...直到s中所有长度为m的子串比较完。

 代码实现(C++,时间复杂度O(N)):

//方法一:暴力枚举法
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ret;//存放符合要求的下标
        int m = p.size(); //记录p的长度
        if(m > s.size()) //处理特殊情况
            return ret;

        int hash1[30]={0};//小写字母个数不会超过30个,用数组模拟哈希表
        for(auto e : p)
            hash1[e-'a']++;

        for(int begin = 0;begin<=s.size()-m;++begin)
        {
            int hash2[30]={0};
            string son = s.substr(begin,m);
            for(auto e : son)
                hash2[e-'a']++;

            //比较hash1和hash2是否相等
            for(int i=0;i<30;++i)
            {
                if(hash1[i]!=hash2[i])
                    break;
                if(i==29) //说明hash1等于hash2
                    ret.push_back(begin); //在结果容器插入起始下标
            }   
        }
        return ret;
    }
};

这种暴力代码虽然能通过,但是将所有子串全部找出依次比较,效率还是太低了,所以我们可以考虑优化一下,分析如下(以示例1为例):

代码实现(C++,时间复杂度O(N)): 

//方法二:滑动指针
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ret;
        int m = p.size();
        int hash1[30]={0};
        for(auto e:p)
            hash1[e-'a']++;
        
        int hash2[30]={0};
        for(int left=0,right=0;right<s.size();++right)
        {
            hash2[s[right]-'a']++; //进窗口
            if(right-left+1 > m) //判断
                hash2[s[left++]-'a']--; //出窗口,更新left

            if(right-left+1 == m)
            {
                //判断hash1和hash2是否相等
                for(int i=0;i<30;++i)
                {
                    if(hash1[i]!=hash2[i])
                        break;
                    if(i==29)
                        ret.push_back(left);
                }
            }
        }
        return ret;
    }
};

此时问题已然解决,但我们还可以对更新结果的判断条件进行优化:

利用count来记录窗口内"有效字符"的个数,所谓有效字符就是能和p中字符进行匹配的字符且数量不能超过p中该字符的个数。那么就可以将更新结果的判断条件改为if(count == m){}这种形式。

代码如下:

//方法二:滑动指针
class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ret;
        int m = p.size();
        int hash1[30]={0};
        for(auto e:p)
            hash1[e-'a']++;
        
        int hash2[30]={0};
        int count = 0; //记录窗口中"有效字符的个数"
        for(int left=0,right=0;right<s.size();++right)
        {
            hash2[s[right]-'a']++; //进窗口
            if(hash2[s[right]-'a'] <= hash1[s[right]-'a'])
                count++;  //说明s[right]这个字符有效

            if(right-left+1 > m) //判断
            {
                if(hash2[s[left]-'a'] <= hash1[s[left]-'a'])
                    count--; //说明s[left]这个字符有效
                hash2[s[left++]-'a']--; //出窗口,更新left
            }

            if(count == m)  
                ret.push_back(left); 
        }
        return ret;
    }
};

四、串联所有单词的子串

30. 串联所有单词的子串 - 力扣(LeetCode)

给定一个字符串 s 和一个字符串数组 words words 中所有字符串 长度相同

 s 中的 串联子串 是指一个包含  words 中所有字符串以任意顺序排列连接起来的子串。

  • 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef", "abefcd""cdabef", "cdefab""efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。

示例 1:

输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。

示例 2:

输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。

示例 3:

输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]
解释:因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。

提示:

  • 1 <= s.length <= 10^4
  • 1 <= words.length <= 5000
  • 1 <= words[i].length <= 30
  • words[i] 和 s 由小写英文字母组成

这道题初看感觉无从下手,但是我们可以以一种特别的眼光来看待此题(以示例1为例):

但它与上道题的有几个不同点:

1、哈希表

上道题中我们是用数组来模拟哈希表的,之所以能这么做是因为在哈希表中存放的是一个个字符。

这道题就不能用数组来模拟哈希表了,因为这道题是以字符串为单位的,所以要用一个容器来存放数据,这里用unordered_map这个容器来记录。

2、left和right指针的移动

这道题中指针每次移动的距离不在是1了,而是单词的长度(len)。

3、滑动窗口的执行次数

上道题中滑动窗口只需执行1次,而这道题中滑动窗口需要执行len次。

代码实现(C++,时间复杂度O(N)):

//方法:滑动窗口
class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ret; //记录最终结果
        unordered_map<string,int> hash1; //存储words中所有单词的频次
        for(auto e:words)
            hash1[e]++;
        
        int len = words[0].size(); //words中每个单词长度相同
        int m = words.size(); //记录words中单词的个数

        for(int i=0;i<len;++i) //滑动窗口执行len次
        {
            unordered_map<string,int> hash2;//维护窗口内单词的频次
            int count = 0; //窗口内有效单词的个数
            //每一次滑动窗口执行过程
            for(int left=i,right=i;right<(int)s.size()-len+1;right+=len) //注意right的更新,s.size()的返回值是无符号整形,它减len可能小于0,所以要强转一下
            {
                //进窗口 + 维护count
                string in = s.substr(right,len);
                hash2[in]++;
                if(hash1.count(in) && hash2[in] <= hash1[in])
                    ++count;

                //判断
                if(right-left+1 > len*m)
                {
                    //出窗口 + 维护count
                    string out = s.substr(left,len);
                    if(hash1.count(out) && hash2[out] <= hash1[out])
                        --count;
                    hash2[out]--;

                    left+=len;
                }

                //更新结果
                if(count == m)
                    ret.push_back(left);
            }
        }
        return ret;
    }
};

五、最小覆盖子串

 76. 最小覆盖子串 - 力扣(LeetCode)

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。

示例 3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

提示:

  • m == s.length
  • n == t.length
  • 1 <= m, n <= 10^5
  • s 和 t 由英文字母组成

 方法一:暴力枚举法。分析如下(以示例1为例):

s中每一趟的结束都是覆盖完t中每一个字符,如果走到末尾还没有覆盖完,那么这个子串就是不满足要求的,想要判断覆盖完全就需要借助哈希表。

暴力解法的代码这里就不演示了,大家学习了上面几道题后应该知道何时使用滑动指针。当我们拿到一个题后想一下滑动指针是否可行,如果可以那么就不必去考虑暴力解法的代码,直接上手滑动指针的代码即可。

这道题还是用滑动指针解题,下面直接分析滑动指针为什么可行:

 和第三道题一样,这里如果用哈希表直接判断则会非常耗时,所以我们可以对更新结果的判断条件进行优化:

利用count来记录窗口内"有效字符"的种类,所谓有效字符的种类就是能和t中字符进行匹配的字符且数量可以超过p中该字符的个数。那么就可以将更新结果的判断条件改为if(count == m){}这种形式。

这道题为什么是有效字符的种类而不是有效字符的个数呢?

举个例子:假设t是"ABC",那s中如果有AAAAAAABBBBBBBBBBC,题目要求的是覆盖完t中的所有字符,所以这种情况符合要求,所以只需看窗口内"有效字符"的种类是否和t中相等即可判断是否全部覆盖。

代码实现(C++,时间复杂度O(N)):

//滑动窗口
class Solution {
public:
    string minWindow(string s, string t) {
        int hash1[130]={0};//所有字符个数不会超过130个,用数组模拟哈希表
        int kinds = 0; //记录t中字符的种类
        for(auto e:t)
        {
            if(hash1[e] == 0)
                ++kinds;
            hash1[e]++;  //用hash1记录t中每个单词出现的频次
        }
        int hash2[130]={0}; //记录窗口内每个字符的频数
        int count = 0; //记录窗口内有效字符的个数
        int begin = -1,minlen = INT_MAX;//记录符合要求的最短长度以及对应的起始位置
        for(int left=0,right=0;right<s.size();++right)
        {
            hash2[s[right]]++; //进窗口
            if(hash2[s[right]] == hash1[s[right]])  //维护count
                ++count;
            //判断
            while(count == kinds)
            {
                 //更新
                if(count == kinds)
                {
                    if(minlen > right-left+1)
                    {
                        minlen=right-left+1;
                        begin = left;
                    }
                }

                 //出窗口
                if(hash2[s[left]] == hash1[s[left]])
                    --count;
                hash2[s[left++]]--;
            }
               
        }  
        if(begin == -1)
            return "";
        else
            return s.substr(begin,minlen);   
    }
};

(完结) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2204593.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用 Hailuo AI 生成视频

在这个科技飞速发展的时代&#xff0c;人工智能已经成为创意领域的重要工具。Hailuo AI 是一个强大的平台&#xff0c;可以帮助你将文字描述转化为高质量的视频。以下是详细的步骤&#xff0c;教你如何使用 Hailuo AI 生成视频。 第一步&#xff1a;访问 Hailuo AI 网站 首先…

第十四章 Java多线程--阻塞队列--SynchronousQueue

目录 一、SynchronousQueue基础概念 主要特点 使用场景 示例代码 二、SynchronousQueue深入了解 1 SynchronousQueue介绍 2 SynchronousQueue核心属性 3 SynchronousQueue的TransferQueue源码 3.1 QNode源码信息 3.2 transfer方法实现 3.3 tansfer方法流程图 一、Sy…

【C++堆(优先队列)】1834. 单线程 CPU|1797

本文涉及知识点 C堆(优先队列) LeetCode1834. 单线程 CPU 给你一个二维数组 tasks &#xff0c;用于表示 n​​​​​​ 项从 0 到 n - 1 编号的任务。其中 tasks[i] [enqueueTimei, processingTimei] 意味着第 i​​​​​​​​​​ 项任务将会于 enqueueTimei 时进入任务…

QStandardItemModel的role

QStandardItemModel定义了一些标准的角色&#xff0c;而QAbstractItemModel允许自定义角色。以下是一些常见的数据角色&#xff1a;1. **Qt::DisplayRole**&#xff1a;这是最基本的角色&#xff0c;用于显示在视图中的文本。当一个单元格被绘制时&#xff0c;通常会查询这个角…

Go 语言应用开发:从入门到实战

Go 语言应用开发&#xff1a;从入门到实战 引言 Go&#xff08;Golang&#xff09;是由 Google 开发的一种开源编程语言&#xff0c;设计初衷是提高编程效率&#xff0c;尤其是在高并发场景下表现出色。Go 语言以其简洁、易学、高效并发的特性&#xff0c;逐渐成为开发者的首…

<Project-8.1.1 pdf2tx-mm> Python 调用 ChatGPT API 翻译PDF内容 历程心得

原因 用ZhipuAI&#xff0c;测试用的PDF里&#xff0c;有国名西部省穆斯林&#xff0c;翻译结果返回 “系统检测到输入或生成内容可能包含不安全或敏感内容&#xff0c;请您避免输入易产生敏感内容的提 示语&#xff0c;感谢您的配合” 。想过先替换掉省名、民族名等&#xff…

DM8数据库用户和表空间管理

1 说明 DM8用户管理和表空间管理常用的管理命令&#xff0c;包括创建、修改和查看信息操作等。 2 用户管理 2.1 创建用户 创建一个用户lu9up&#xff0c;密码为"admin2024."&#xff0c;未制定表空间&#xff0c;使用默认的表空间main。 SQL> create user lu…

银河麒麟桌面操作系统V10:解决激活时“无法获取硬件信息(错误码#0017)”问题

银河麒麟桌面操作系统V10&#xff1a;解决激活时“无法获取硬件信息&#xff08;错误码#0017&#xff09;”问题 1、问题描述2、问题解决方法步骤一&#xff1a;打开终端步骤二&#xff1a;删除/etc/.kyhwid文件步骤三&#xff1a;重新激活系统总结 &#x1f490;The Begin&…

【Ubuntu】在Ubuntu上安装IDEA

【Ubuntu】在Ubuntu上安装IDEA 零、前言 最近换了Ubuntu系统&#xff0c;但是还得是要写代码&#xff0c;这样就不可避免地用到IDEA&#xff0c;接下来介绍一下如何在Ubuntu上安装IDEA。 壹、下载 这一步应该很容易的&#xff0c;直接打开IDEA的下载页面&#xff0c;点击下…

Python RabbitMQ 入门 pika

Python RabbitMQ 入门 RabbitMQ是实现了高级消息队列协议&#xff08;AMQP&#xff09;的开源消息代理软件&#xff08;亦称面向消息的中间件&#xff09;。RabbitMQ服务器是用Erlang语言编写的&#xff0c;而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均…

基于vue的酒店预订管理系统(源码+定制+开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

Paperless-ngx文档管理系统本地部署并实现远程使用搜索查阅文件

文章目录 前言1. 部署Paperless-ngx2. 本地访问Paperless-ngx3. Linux安装Cpolar4. 配置公网地址5. 远程访问6. 固定Cpolar公网地址7. 固定地址访问 前言 本文主要介绍如何在Linux系统本地部署Paperless-ngx开源文档管理系统&#xff0c;并结合cpolar内网穿透工具解决本地部署…

Visual Studio 2022安装(含重生版)

前言&#xff1a; 昨天调试代码的时候发现程序怎么都运行不了&#xff0c;错误显示无法找到文件啊啊啊&#xff0c;能力有限&#xff0c;找不出错误源&#xff0c;然后就狠心删掉所有相关文件来“重新开始”&#xff01; 正文&#xff1a; 1.官网下载&#xff08;内定中文版…

欧科云链研究院深掘链上数据:洞察未来Web3的隐秘价值

目前链上数据正处于迈向下一个爆发的重要时刻。 随着Web3行业发展&#xff0c;公链数量呈现爆发式的增长&#xff0c;链上积聚的财富效应&#xff0c;特别是由行业热点话题引领的链上交互行为爆发式增长带来了巨量的链上数据&#xff0c;这些数据构筑了一个行为透明但与物理世…

前后分离项目记录

一.前端设置 1.打包问题 打包报错 Thread Loader时&#xff0c;增加以下代码&#xff1a; 上线&#xff0c;打包prod时: 2.上线时api设置 二.Nginx问题 1.缓存问题&#xff1a;添加如下代码以禁止缓存&#xff0c;否则在关闭nginx后仍然可以访问页面 2.跨域问题在后端加Cr…

六西格玛设计DFSS方法论在消费级无人机设计中的应用——张驰咨询

本文基于六西格玛设计方法论&#xff0c;对消费级无人机的设计流程进行系统化研究&#xff0c;探讨如何通过六西格玛设计的理念、工具和方法提升无人机产品的设计质量和市场竞争力。文章从市场定位、客户需求分析出发&#xff0c;深入到关键KPI指标的制定&#xff0c;并逐步阐述…

十、索引优化与查询优化

文章目录 1. 数据准备2. 索引失效案例2.1 全值匹配我最爱2.2 最佳左前缀法则2.3 主键插入顺序2.4 计算、函数、类型转换(自动或手动)导致索引失效2.5 类型转换导致索引失效2.6 范围条件右边的列索引失效2.7 不等于(!=或者<>)索引失效2.8 is null 可以使用索引,is not …

STM32 USB CUBEMX

开发背景 使用的平台&#xff1a;STM32H750 注意事项 时钟必须是48MHZ&#xff0c;其它都不行 2. 将默认任务的堆栈设大一点 如果使用操作系统&#xff0c;USB任务跑在默认任务里&#xff0c;因此需要设置默认任务的堆栈缓存是直接定义的全局变量&#xff0c;需要设置编译器…

通过阿里云Milvus和通义千问快速构建基于专属知识库的问答系统

本文展示了如何使用阿里云向量检索Milvus和灵积&#xff08;Dashscope&#xff09;提供的通用千问大模型能力&#xff0c;快速构建一个基于专属知识库的问答系统。在示例中&#xff0c;我们通过接入灵积的通义千问API及文本嵌入&#xff08;Embedding&#xff09;API来实现LLM大…

中标麒麟操作系统:如何查看系统激活状态

中标麒麟操作系统&#xff1a;如何查看系统激活状态 1、图形界面查看方法方法一&#xff1a;任务栏查看方法二&#xff1a;通过“我的电脑”属性查看 2、命令行查看方法 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 本文将介绍两种查看系…