首页 > 其他分享 >【leetcode】将x减到0的最小操作数/水果成篮/找到字符串中所有字母异位词{史上最容易懂的解析}

【leetcode】将x减到0的最小操作数/水果成篮/找到字符串中所有字母异位词{史上最容易懂的解析}

时间:2024-04-04 18:58:05浏览次数:21  
标签:字符 操作数 right 窗口 ++ int 成篮 leetcode left

文章目录

1.将x减到0的最小操作数

在这里插入图片描述
在这里插入图片描述

分析题目

x不断地减去数组两端的值 看能否减到0;是不是就是在问:nums数组中存不存在【左端+右端】组成的连续区间,区间上数的和为x 继续分析 ==》 是不是就是在问:nums数组中存不存在内部的一段连续区间,区间上的数的和为sum(nums) - x 很明显,这是个经过分析的【滑动窗口】问题

代码

class Solution
{
public:
    int minOperations(vector<int> &nums, int x)
    {
        int sum = 0;
        for (int a : nums)
            sum += a;
        int target = sum - x;

        //x比sum大 sum中就不会存在几个数的和==x
        if (target < 0)
            return -1;

        int ret = -1;
        for (int left = 0, right = 0, tmp = 0; right < nums.size(); right++)
        {
            tmp += nums[right];     
            while (tmp > target)     
                tmp -= nums[left++]; 
            if (tmp == target)       
                ret = max(ret, right - left + 1);
        }
        
        if (ret == -1)
            return ret;
        else
            return nums.size() - ret;
    }
};

2.水果成篮

在这里插入图片描述
在这里插入图片描述

分析

依旧是滑动窗口,一个区间,该区间内水果种类不能超2,超2就将下一个元素作为区间的起始位置

代码

class Solution
{
public:
    int totalFruit(vector<int> &f)
    {
        // i是树的下标 fruits[i]是水果的种类编号 fruits[i]: 0~100000
        int hash[100001] = {0}; // 以水果的种类编号作hash的下标 对应值记录该种水果出现次数

        int ret = 0;
        for (int left = 0, right = 0, kinds = 0; right < f.size(); right++)
        {
            // 当前遍历的该水果在篮子里的次数是0 种类++
            if (hash[f[right]] == 0)
                kinds++;

            // 当前遍历的该水果可以出现在篮子里
            hash[f[right]]++;

            while (kinds > 2)
            {
                // left作起始位置的这个区间已达最大长度 继续遍历 将下一个元素作为区间的起始位置
                hash[f[left]]--;        // 出窗口 水果次数--
                if (hash[f[left]] == 0) // 如果拿出窗口的水果在原来的篮子里是独苗 种类也--
                    kinds--;
                left++; // 继续下一个元素作为区间的起始位置
            }
            ret = max(ret, right - left + 1);
        }
        return ret;
    }
};

cpp_stl容器unordered_map

class Solution
{
public:
    int totalFruit(vector<int> &f)
    {
        unordered_map<int, int> hash; 

        int ret = 0;
        for (int left = 0, right = 0; right < f.size(); right++)
        {
            hash[f[right]]++;      
            while (hash.size() > 2) 
            {
                hash[f[left]]--;
                if (hash[f[left]] == 0)
                    hash.erase(f[left]);
                left++;
            }
            ret = max(ret, right - left + 1);
        }
        return ret;
    }
};

3.找到字符串中所有字母异位词

在这里插入图片描述

在这里插入图片描述

滑动窗口的分类

  1. 区间长度固定如本题
  2. 左指针疯狂右移 right不动
  3. 右指针疯狂右移 left不动

总体思路:这道题【维护窗口的时机】发生在窗口的长度超过了p的长度,保证窗口的长度只能不大于p的长度

遍历母串,遍历到who,不管符不符合条件,who就先进窗口,如果who是一个【有效字符】即【可以作为异位词的字符】即【在p中出现且次数不超过在p中出现的字符】,接着上一句,如果who是一个【有效字符】,那么有效字符个数validChar++; 经过不断遍历,如果窗口的长度已经大于p的长度,窗口就要右移了,即left++; 并且left在窗口中的次数也要winHash[out - 'a']--; 需要注意的是,如果移出去的left,他对应的值在窗口中出现的次数大于在p中出现的次数,left移出后,有效字符个数不变,left出去正是我们想要的,这个操作表明窗口中少了一个不该出现的字符,这使得区间中的字符越来越接近我们想要的字符组合即异位词。上述操作保证了窗口的长度只能不大于p的长度。接着再判断,如果此时窗口中的有效字符个数 == p的长度,表示我们找了“异位词”。如果此时validChar != pLen 表示: 虽然窗口的长度到达了pLen,但是窗口中的字符并不是全部有效,还要继续添加新元素,来满足:窗口的长度为pLen且均为有效字符。

代码 + 史上最全解析

class Solution
{
public:
    vector<int> findAnagrams(string s, string p)
    {
        vector<int> ret;
        int sLen = s.size(), pLen = p.size(), validChar;

        // 母串长度比子串长度还小 直接返回
        if (sLen < pLen)
            return ret;

        // p字符串有哪些字符 分别出现了多少次
        // phash中值不为0的下标代表有哪些字符 值就是它出现的次数
        int pHash[26] = {0};
        for (auto ch : p)
            pHash[ch - 'a']++;

        // 记录窗口中有哪些字符以及对应出现的次数
        int winHash[26] = {0};

        // 要理解这种写法 要理解两个关键字
        // 1. winHash  :窗口中有哪些字符以及对应出现的次数
        // 2. validChar:窗口中有效字符的个数
        for (int left = 0, right = 0, validChar = 0; right < s.size(); right++)
        {
            // in:即将进入窗口的字符
            char in = s[right];

            // 遍历到in了 in默认进窗口 用【in在窗口中的次数++】来表征in进窗口了
            // 如果此时窗口中in的次数大于p中in的次数 那么in是作为一个无效字符进的窗口 有效字符个数不变
            // 如果此时窗口中in的次数不大于p中in的次数 表明in此时在窗口中是一个有效字符 有效字符个数++
            if (++winHash[in - 'a'] <= pHash[in - 'a'])
                validChar++;

            // 窗口的长度已经大于子串了
            if (right - left + 1 > pLen)
            {
                char out = s[left++];

                // out在窗口中出现的次数 <= out在p中出现的次数 有效字符个数--
                // 反向理解
                // 如果out在窗口中出现的次数 > out在p中出现的次数
                // out移出后 有效字符个数不变 out出去正是我们想要的 窗口中少了一个不该出现的字符
                // 这使得区间中的字符越来越接近我们想要的字符组合了即异位词
                if (winHash[out - 'a']-- <= pHash[out - 'a'])
                    validChar--;
            }

            // 前面两个if保证窗口的窗口不会超过p的长度
            // 如果此时validChar == pLen即窗口中的有效字符个数等于p的长度 表示我们找了“异位词”
            // 如果此时validChar != pLen 表示: 虽然窗口的长度到达了pLen 但是窗口中的字符并不是全部有效
            // 还要继续添加新元素 来满足:窗口的长度为pLen且均为有效字符
            if (validChar == pLen)
                ret.push_back(left);
        }
        return ret;
    }
};

标签:字符,操作数,right,窗口,++,int,成篮,leetcode,left
From: https://blog.csdn.net/LHRan_ran_/article/details/137326753

相关文章

  • Java | Leetcode Java题解之第10题正则表达式匹配
    题目:题解:classSolution{publicbooleanisMatch(Strings,Stringp){intm=s.length();intn=p.length();boolean[][]f=newboolean[m+1][n+1];f[0][0]=true;for(inti=0;i<=m;++i){......
  • Java | Leetcode Java题解之第9题回文数
    题目:题解:classSolution{publicbooleanisPalindrome(intx){//特殊情况://如上所述,当x<0时,x不是回文数。//同样地,如果数字的最后一位是0,为了使该数字为回文,//则其第一位数字也应该是0//只有0满足这一属......
  • Java | Leetcode Java题解之第8题字符串转换整数atoi
    题目:题解:classSolution{publicintmyAtoi(Stringstr){Automatonautomaton=newAutomaton();intlength=str.length();for(inti=0;i<length;++i){automaton.get(str.charAt(i));}retur......
  • Java | Leetcode Java题解之第7题整数反转
    题目:题解:classSolution{publicintreverse(intx){intrev=0;while(x!=0){if(rev<Integer.MIN_VALUE/10||rev>Integer.MAX_VALUE/10){return0;}intdigit=x......
  • 稀碎从零算法笔记Day37-LeetCode:所有可能的真二叉树
    今天的每日一题,感觉理解的还不够深,有待加深理解题型:树、分治、递归链接:894.所有可能的真二叉树-力扣(LeetCode)来源:LeetCode题目描述给你一个整数 n ,请你找出所有可能含 n 个节点的 真二叉树 ,并以列表形式返回。答案中每棵树的每个节点都必须符合 Node.val==0 ......
  • 稀碎从零算法笔记Day36-LeetCode:H指数
    有点绕的一个题,题目描述的有点奇怪(可以看下英文?)题型:数组、模拟链接:274.H指数-力扣(LeetCode)来源:LeetCode题目描述给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。根据维基百科上 h指数......
  • 【Leetcode】top 100 技巧
    136只出现一次的数字给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。技巧:异或  相同为0,剩到最后的数值只出现一次;c......
  • leetcode每日一题 1379. 找出克隆二叉树中的相同节点
    问题描述给你两棵二叉树,原始树original和克隆树cloned,以及一个位于原始树original中的目标节点target。其中,克隆树cloned是原始树original的一个副本。请找出在树cloned中,与target相同的节点,并返回对该节点的引用(在C/C++等有指针的语言中返回节点指针,其他......
  • LeetCode-1379. 找出克隆二叉树中的相同节点【树 深度优先搜索 广度优先搜索 二叉树】
    LeetCode-1379.找出克隆二叉树中的相同节点【树深度优先搜索广度优先搜索二叉树】题目描述:解题思路一:递归,由于我们比较的是节点而不是节点值(例如C++比较的是地址),所以下面的代码也适用于树中有值相同节点的情况(本题的进阶问题)。解题思路二:递归这题有几个关键点,一:判......
  • LeetCode-146. LRU 缓存【设计 哈希表 链表 双向链表】
    LeetCode-146.LRU缓存【设计哈希表链表双向链表】题目描述:解题思路一:双向链表,函数get和put必须以O(1)的平均时间复杂度运行。一张图:解题思路二:0解题思路三:0题目描述:请你设计并实现一个满足LRU(最近最少使用)缓存约束的数据结构。实现LRUCache类:LR......