C++: Leetcode-Sliding Window-904. Fruits into Baskets

C++: Leetcode-Sliding Window-904 Fruits into Baskets

Focus on mastering the idea of ​​sliding windows, the meanings of the left and right pointers.
Focus on familiarizing yourself with the use of hash tables for statistics and duplicate checking.
In the face of this kind of statistical problems of the same type or duplicate checking problems, the hash table is the best choice



topic

You are visiting a farm with a row of fruit trees planted from left to right. These trees are represented by an integer array fruits, where fruits[i] is the fruit type on the i-th tree.

You want to collect as many fruits as possible. However, the owner of the farm has set some strict rules that you must follow to pick the fruit:

You only have two baskets, and each basket can only hold a single type of fruit. There is no limit to the total amount of fruit each basket can hold.
You can choose any tree to start picking, and you must pick exactly one fruit from each tree (including the tree you started picking). Fruit picked should match the type of fruit in the basket. Each time you pick, you will move right to the next tree and continue picking.
Once you get to a tree and the fruit doesn't fit the type of fruit in your basket, then you have to stop picking.
Given an integer array fruits, return the maximum number of fruits you can collect. Familiarize yourself with the role of hash tables and their advantages, knowing when and how to use them.

Solution 1: Use array space or vector space as hash table storage

Idea analysis :
1. Move the right pointer to the right, record each category and its quantity during the movement, use the hash table to make statistics, and record the length of the left and right pointers in turn, that is, the maximum number of collected fruits 2. When the category >
2 , the left pointer starts to move, and decreases the number of corresponding types from the left until the type == 2, and then records the length of the left and right pointers, that is, the maximum number of fruits collected 3. Continuously loop until the right pointer moves to the rightmost
end

Important and difficult points : record the category and its quantity; the left pointer deletes the corresponding quantity in turn; the method adopted is to use the hash table

/*
Leetcode-滑动窗口-904题
题目:
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

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

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

 


知识点:
1.面对这种同类型数量统计问题或者是查重问题,哈希表是不二之选,需熟练掌握哈希表的性质,知道何时使用该使用哈希表
2.提高自我熟练调试程序流程能力

方法:
方法一,采用vector或者数组作哈希表统计查重
方法二,采用map进行统计查重!

思路分析:
1、右指针向右移动,记录移动过程中每一个种类类别,及其数量,使用哈希表进行统计,并依次记录左右指针长度,即收集水果最大数目
2、当种类类别>2时,左指针开始移动,并从左边依次减少对应种类的数量,直至种类类别==2,然后记录此次左右指针长度,即收集水果最大数目
3、不断循环,直至右指针移动至最右端
*/

#include "iostream"
#include "vector"
#include "set"
using namespace std;

//方法一
//哈希表进行统计查重的思想,建立简易哈希表
//用vector进行哈希表存储
class Solution
{
    
    
public:
    Solution(/* args */) {
    
    }
    ~Solution() {
    
    }
    int totalFruit(vector<int> &fruits)
    {
    
    

        //int res[100000] = {0}; //建立大空间,用于进行哈希表计数,建立空间太小测试会不通过
        vector<int> res(100000); //建立大空间,用于进行哈希表计数
        int classSum = 0;        //种类数目
        int ans = 0;
        //i终止指针,j起始指针
        for (int i = 0, j = 0; i < fruits.size(); i++)
        {
    
    
            //判断是否为新种类
            //此方法为建议哈希表,把内容当成另一个数组下标来计数
            if (res[fruits[i]] == 0)
            {
    
    
                classSum++;
            }
            res[fruits[i]]++; //该fruits[i]种类的果树数量+1
            while (classSum > 2)
            {
    
    
                res[fruits[j]]--;
                if (res[fruits[j]] == 0)
                {
    
    
                    classSum--;
                }

                j++;
            }
            ans = ans > (i - j + 1) ? ans : (i - j + 1);
        }
        return ans;
    }
};

int main(int argc, char const *argv[])
{
    
    
    //测试
    vector<int> fruits;
    fruits.push_back(0);
    fruits.push_back(1);
    fruits.push_back(2);
    fruits.push_back(2);

    Solution s1;
    cout << s1.totalFruit(fruits) << endl;

    return 0;
}

Solution 2: Use unordered_map as hash table storage

The unordered_map container, like the map container, stores data in the form of key-value pairs (pair type), and the keys of each stored key-value pair are different from each other and cannot be modified.
However, since the bottom layer of the unordered_map container uses a hash table storage structure , the structure itself does not have the function of sorting data , so the key-value pairs stored in this container will not be sorted by itself.

The thinking analysis is consistent with the solution one, but the solution two uses the unordered_map container

/*
Leetcode-滑动窗口-904题
题目:
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。

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

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

 


知识点:
1.面对这种同类型数量统计问题或者是查重问题,哈希表是不二之选,需熟练掌握哈希表的性质,知道何时使用该使用哈希表
2.提高自我熟练调试程序流程能力

方法:
方法一,采用vector或者数组作哈希表统计查重
方法二,采用maunordered_map进行统计查重!
由于 unordered_map 容器底层采用的是哈希表存储结构,该结构本身不具有对数据的排序功能,所以此容器内部不会自行对存储的键值对进行排序。


思路分析:
1、右指针向右移动,记录移动过程中每一个种类类别,及其数量,使用哈希表进行统计,并依次记录左右指针长度,即收集水果最大数目
2、当种类类别>2时,左指针开始移动,并从左边依次减少对应种类的数量,直至种类类别==2,然后记录此次左右指针长度,即收集水果最大数目
3、不断循环,直至右指针移动至最右端
*/

#include "iostream"
#include "vector"
#include "set"
#include "unordered_map"
using namespace std;

//方法二
//使用unordered_map
//由于 unordered_map 容器底层采用的是哈希表存储结构,该结构本身不具有对数据的排序功能,所以此容器内部不会自行对存储的键值对进行排序。

class Solution
{
    
    
public:
    Solution(/* args */) {
    
    }
    ~Solution() {
    
    }
    int totalFruit(vector<int> &fruits)
    {
    
    
        int ans = 0;
        int classNum = 0;
        //底层采用哈希表存储结构
        unordered_map<int, int> hashmap;
        for (int i = 0, j = 0; i < fruits.size(); i++)
        {
    
    
            if (hashmap[fruits[i]] == 0)
            {
    
    
                classNum++;
            }
            hashmap[fruits[i]]++;
            while (hashmap.size() > 2) //种类数目大于2
            {
    
    
                hashmap[fruits[j]]--; //减少左指针对应种类的值
                if (hashmap[fruits[j]] == 0)
                {
    
    
                    hashmap.erase(fruits[j]); //当此fruits[j]类别的数量为0时,应erase进行删除,不然会影响size的判断
                    classNum--;
                }

                j++;
            }
            ans = ans > (i - j + 1) ? ans : (i - j + 1); //取最大值
        }
        return ans;
    }
};

int main(int argc, char const *argv[])
{
    
    
    //测试
    vector<int> fruits;
    fruits.push_back(0);
    fruits.push_back(1);
    fruits.push_back(2);
    fruits.push_back(2);

    Solution s1;
    cout << s1.totalFruit(fruits) << endl;

    return 0;
}



Summarize

Familiar with the idea of ​​sliding window and double pointer.
Familiarize yourself with the role of hash tables and their advantages, knowing when and how to use them.

Guess you like

Origin blog.csdn.net/Bellwen/article/details/128185472