LeetCode刷题笔记 ---(七)

刚发完一篇博客,过来刷会儿题

ID:994

image-20240131182712565

简单的一道BFS,感觉BFS就是写起来麻烦一点,思路还是很清晰的

answer:

class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        vector<vector<int>> steps={{-1,0},{1,0},{0,1},{0,-1}};
        int res=0;
        vector<vector<int>> visit(grid.size(),vector<int>(grid[0].size(),0));
        int count_fresh=0;
        queue<pair<int,int>> bfs;
        for(int i=0;i<grid.size();i++){
            for(int j=0;j<grid[0].size();j++){
                if(grid[i][j]==1){
                    count_fresh++;
                }
                if(grid[i][j]==2){
                    bfs.push({i,j});
                }
            }
        }
        if(count_fresh==0)return 0;
        if(bfs.empty())return -1;
        while(!bfs.empty()){
            int count=bfs.size();
            while(count--){
                auto now=bfs.front();bfs.pop();
                visit[now.first][now.second]=1;
                for(auto step:steps){
                    int next_x=now.first+step[0];
                    int next_y=now.second+step[1];
                    if(next_x>=0&&next_x<grid.size()&&next_y>=0&&next_y<grid[0].size()){
                        if(grid[next_x][next_y]==1&&visit[next_x][next_y]==0){
                            count_fresh--;
                            visit[next_x][next_y]=1;
                            grid[next_x][next_y]=2;
                            bfs.push({next_x,next_y});
                        }
                    }
                }
            }
            res++;
        }
        if (count_fresh==0) return res-1;
        return -1;
    }
};

tips:记得提前处理特殊情况,如没有烂橘子,或者没有新鲜橘子


2024.2.5 终于拿到驾照了,继续加油,希望新的一年爱情事业双丰收,加油!

ID:49

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

思路历程:

一开始想到了用哈希,然后看了眼提示,确实是。

确认之后一开始想着用哈希表组,每组记录字符串单词,

后来想开了,用sort函数排完序后,都是一样的,这样直接插入哈希表就行

answer:

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        int n= strs.size();
        if(n==0)return{{}};
        map<string,vector<string>> all_string;
        vector<vector<string>> res;
        for(int i=0;i<n;i++){
            string right_string=strs[i];
            sort(strs[i].begin(),strs[i].end());
            all_string[strs[i]].push_back(right_string);
        }
        for(auto c:all_string){
            res.push_back(c.second);
        }
        return res;
    }
};

ID:118

给定一个非负整数 *numRows,*生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

思路历程:

可以用递归,也可以直接加

answer:

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        if(numRows==1)return {{1}};
        if(numRows==2)return {{1},{1,1}};
        vector<vector<int>> res;
        res.push_back({1});res.push_back({1,1});
        int i=2;
        while(i<numRows){
            vector<int>tmp;
            tmp.push_back(1);
            for(int j=0;j<i-1;j++){
                tmp.push_back(res[i-1][j]+res[i-1][j+1]);
            }
            tmp.push_back(1);
            res.push_back(tmp);
            i++;
        }
        return res;
    }
};

今天有点累,做一道简单的先休息吧


ID:128

新年快乐!2024.2.11

这篇拖的好像有点久了,没时间难过了,即将到来的是新年第一题!

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

思路历程:

注意点主要在于遇到重复的数字别忘了跳过

answer:

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int n= nums.size();
        int i=0;
        int res=0;
        if(!n)return 0;
        int tmp_max=1;
        while(i<n-1){
            if(nums[i+1]==nums[i]+1){
                tmp_max++;
            }else if(nums[i+1]==nums[i]){
                i++;
                continue;
            }else{
                res=max(res,tmp_max);
                tmp_max=1;
            }
            i++;
        }
        return max(res,tmp_max);
    }
};

ID:300

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

思路历程:

唉,一开始想着用栈去解决,但是不太对啊,因为每次压栈都是以栈顶为标准,一旦出现1,3,2,3就会出现1,3压栈后,2,3无法入栈

最终结果变为2,而不是3。

所以还是要记录状态,既然要记录状态,那么很容易联想到DP

作为DP去解决的话,思路就很清晰了,向后遍历的同时,向前遍历,找出深度最大且比自己小的值,然后+1

answer:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n=nums.size();
        if(n==1)return 1;
        int i=0;
        vector<int>res(nums.size(),1);
        int res_max=1;
        while(i<n){
            if(i>0){
                int tmp_max=0;
                for(int j=i;j>-1;j--){
                    if(nums[j]<nums[i]){
                        tmp_max=max(tmp_max,res[j]);
                    }
                }
                cout<<tmp_max<<endl;
                res[i]=tmp_max+1;
                res_max=max(res_max,res[i]);
            }
            i++;
        }
        return res_max;
    }
};

ID:42

image-20240211142342647

思路历程:

一开始想着单调栈,但后来发现和之前一道股票题有点像

都是单调性入手,如果递增结束,就寻找之前的最高点

最高点比自己高,就以自己为参照,如果最高点比自己低,就以最高点为参照

同时,由于可能出现42324这种情况,还需要在更新状态的同时,清空老状态

之前一直都陷入了思维误区,一直以为峰值才能接水,实际上,只要开始出现递增,就可以进行接水。

哪怕多接了,也没关系,可以在后续的接水中清除之前的状态

这里要注意一个问题,就是在找前点的时候,遇到比自己大的第一个点就得停下。如果没有就找前面的最大值

answer:

class Solution {
public:
    int trap(vector<int>& height) {
        int n=height.size();
        vector<int>state(height.size(),0);
        int i=1;
        while(i<n){
            if(height[i]>height[i-1]){
        		//往前找的过程中,如果遇到比自己大的,可以直接停下来
        		//如果没有,就遍历找一个最大值
                int tmp_max=0;
                int max_left=0;
                for(int j=i-1;j>-1;j--){
                    if(height[i]<=height[j]){
                        max_left=j;
                        tmp_max=height[j];
                        break;
                    }
                    if(tmp_max<=height[j]){
                        max_left=j;
                        tmp_max=height[j];
                    }
                }
                state[i]=(i-max_left-1)*min(height[i],tmp_max);
                for(int j=max_left+1;j<i;j++){
                    state[i]-=height[j];
                    state[j]=0;
                }
            }   
            i++;
        }
        i=0;
        int res=0;
        while(i<n)res+=state[i++];
        return res;
    }
};

题解当中的解法更加简单一点,可以选择单调栈,也可以选择DP


ID:189

image-20240220142507639

思路历程:

...很快,很简单

多开一个数组的话非常快,改下下标然后重新赋值数组就行

answer:

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int> res(n,0);
        int i=0;
        k=k%n;
        int tmp_i=n-k;
        int j=0;
        while(k+j<n){
            res[k+j]=nums[j];
            j++;
        }
        while(i<n){
            if(tmp_i+i<n){
                res[i]=nums[tmp_i+i];
                i++;
            }else break;
        }
        nums=res;
    }
};

ID:76

image-20240220160513054

思路历程:

好难的一道题,如果t内的字母不会重复还好,可以双指针一点点往内部缩小范围

但如果有字母重复,那该怎么办

哈希表尝试一下,先将子串全部纳入哈希表,second用来记录个数

我利用双指针,一个从左往右,一个从右往左

如果如果s的哈希表数值等于t了,就停止

通过了一部分样例,但遇到这个例子该怎么办cabwefgewcwaefgcf

刚才的想法还行,但是如果实现的时候先左指针动,然后右指针动,容易出现结果靠右;右指针先动同理


看了题解后:

  • 我可以右指针和左指针同时从起点出发

  • 右指针往右走的时候,将S的map记录进去,而不是一开始就记录

    一开始就记录的话,窗口内是否满足不能确定,所以滑动窗口的灵魂就在于,每次满足窗口内状态满足(或者富余了,再进行缩减窗口)

  • 加个计数器来验证状态

    如果t中的计数次数>=s,则纳入窗口

    检查i的状态,如果s中的字母多了,i往右走

    每次查看计数器是否达到t的大小

class Solution {
public:
    string minWindow(string s, string t) {
        int m=s.size();
        int n=t.size();
        map<char,int> t_map;
        map<char,int> s_map;
        if(n>m)return "";
        //记录t的字母
        for(int i=0;i<n;i++){
            if(t_map.find(t[i])!=t_map.end()){
                t_map[t[i]]++;
            }else{
                t_map[t[i]]=1;
            }
        }
        int i=0;
        int count=0;
        string res=s;
        bool flag=false;
        for(int j=0;j<m;j++){
            s_map[s[j]]++;
            if(t_map[s[j]]>=s_map[s[j]]) count++;
            while(s_map[s[i]]>t_map[s[i]]) --s_map[s[i++]];
            if(count==n){
                if(j-i+1<=res.size()){
                    flag=true;
                    res=s.substr(i,j-i+1);
                }
            }
        }
        if(flag)return res;
        else return "";
    }
};

为什么计数器只加不减?

因为某个字母数量满足,计数器就不会再加

不满足才会加,所以一旦到t的大小,就说明每个字母都满足了

那么什么时候更新呢?

就在左指针所在字母的数量超标时,更新,直到当前字母未达标

为什么需要flag?

因为有时候没有匹配到相应子串,需要返回空


这篇博客拖了好久,虽然没什么人看,但还是要和自己说声抱歉

休息可以,懈怠不行

共勉

文章作者: P4ul
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 打工人驿站
算法 c++
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝