【力扣打卡--day4】【有注释有思路】

1.排序

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

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string,vector<string>> hash;
        //异构字符串都能按升序排列成同一字符串啊
        vector<vector<string>> res;
        for(auto& s:strs){
            string t=s;
            sort(t.begin(),t.end());
            hash[t].push_back(s);//同一类异构字符串
        }

        for(auto& s:hash){
            res.push_back(s.second);
        }
        return res;
    }
};

思路

  • 因为同一类型异构字符串其实都是一组相同字母的组合排列,所以只需找一个他们都能转换过去的形式来表示就能统计了。所以可按升序来做比较好,因为sort能排序字符串字母。这样就能归类了,同一类的字符串sort后都是相同的,可采用map来存储。

2.位运算(快速幂)

在这里插入图片描述

class Solution {
public:
    double myPow(double x, int n) {
        typedef long long LL;
        double res=1;
        bool is_minus=false;
        if(n<0) is_minus=true;//符号
        for(LL i=abs(LL(n));i;i>>=1){//每次n都去掉最后一位
            if(i&1) res*=x;//指数n的最后一位是1,
            //n的二进制表示相应的一位就是1,也就是乘上底数的相应的指数次方
            //相当于讲n拆成2进制表示,x的n次方就是x的2进展表示次方合起来
            x*=x;
        }
        if(is_minus) return 1/res;//负数
        return res;
    }
};

思路
在这里插入图片描述

  • 将n拆成2进制表示,因为n是指数,要让它相加,只有是res结果每次是相乘啊,快速幂。

3.bfs

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

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& ma) {
        vector<int> res;
        int n=ma.size();
        if(!n) return res;
        int m=ma[0].size();

        vector<vector<bool>> st(n,vector<bool>(m));//防重走
        int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};//走到边界就换方向

        for(int i=0,x=0,y=0,d=0;i<m*n;i++){
            res.push_back(ma[x][y]);
            st[x][y]=true;

            int a=x+dx[d],b=y+dy[d];//试着走过去
            if(a<0||b<0||a==n||b==m||st[a][b]){//边界判断
                d=(d+1)%4;//走到边界就换方向
                a=x+dx[d],b=y+dy[d];//换方向了就把a和b重新算
            }
            x=a,y=b;//真正的走过去
        }
        return res;
    }
};

思路

  • 走到边界就换方向,bfs,向量。

4.贪心

在这里插入图片描述

class Solution {
public:
    bool canJump(vector<int>& nums) {
        for(int i=0,j=0;i<nums.size();i++){
            if(j<i) return false;//当前的点跳不到噢
            j=max(j,nums[i]+i);//跳到当前点了,看看跳跃距离有没有变大
        }
        return true;
    }
};

思路

  • 每次要走一步先看看能跳到当前这一步吗,能就更新跳跃能力。

5.双指针

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& a) {
        vector<vector<int>> res;
        if(a.empty()) return res;
        sort(a.begin(),a.end());//按起点排序
        int l=a[0][0],r=a[0][1];//第一段
        for(int i=1;i<a.size();i++){
            if(a[i][0]>r){//要到的区间起点比之前的尾要大,那之前的无法合并了,装好之前的段
                res.push_back({l,r});
                l=a[i][0],r=a[i][1];//双指针换到新来的一段区间上
            }
            r=max(r,a[i][1]);//r每次都看能不能更大,因为只要尾够大就能合并其他区间进段
        }
        res.push_back({l,r});//最后一段
        return res;
    }
};

思路
在这里插入图片描述

  • 每次走都能看看嘴能不能继续增大,嘴装不下了就吞再继续塞新来的东西在嘴上。

6.贪心

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

class Solution {
public:
    vector<vector<int>> insert(vector<vector<int>>& a, vector<int>& b) {
        vector<vector<int>> res;
        int k=0;
        while(k<a.size()&&a[k][1]<b[0]) res.push_back({a[k++]});//第一段和插入的区间无交集

        if(k<a.size()){
            b[0]=min(b[0],a[k][0]);//有交集的看看谁左边最小
            while(k<a.size()&&a[k][0]<=b[1]) b[1]=max(b[1],a[k++][1]);//只要头都在插入区
            //间尾前面,同时更新尾
        }
        res.push_back(b);//装入插入区间所在段
        
        while(k<a.size()) res.push_back({a[k++]});//最后一段

        return res;
    }
};

思路
在这里插入图片描述

  • 分三段,分情况讨论,插入区间那段就是贪心

7.bfs

在这里插入图片描述

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res=vector<vector<int>>(n,vector<int>(n));
        if(!n) return res;

        vector<vector<bool>> st(n,vector<bool>(n));
        int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};

        for(int i=1,x=0,y=0,d=0;i<=n*n;i++){
            res[x][y]=i;
            st[x][y]=true;
            int a=x+dx[d],b=y+dy[d];
            if(a<0||b<0||a==n||b==n||st[a][b]){
                d=(d+1)%4;
                a=x+dx[d],b=y+dy[d];
            }
            x=a,y=b;
        }
        return res;
    }
};

思路

  • bfs走到边界就换方向,同前面某题。

8.链表

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

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* rotateRight(ListNode* head, int k) {
        if(head==NULL) return NULL;
        ListNode* r;
        int n=0;
        for(auto i=head;i;i=i->next){
            n++;//算共有几个节点 
            r=i;
        }
        int k0=k%n;//旋转几个点
        if(!k0) return head;
        ListNode* l=head;
        for(int i=0;i<n-k0-1;i++){
            l=l->next;
        }
        r->next=head;//屁股连头
        ListNode* res=l->next;//旋转后的头
        l->next=NULL;//旋转后的尾断尾
        return res;
    }
};

思路

  • 画图自己看吧

9.dp

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

class Solution {
public:
    int uniquePaths(int m, int n) {
        if(!n) return 0;
        vector<vector<int>> f(n,vector<int>(m));
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(!i&&!j) f[i][j]=1;//第一行第一列
                else{
                    if(i) f[i][j]+=f[i-1][j];//能从上边下来
                    if(j) f[i][j]+=f[i][j-1];//能从左边过来
                }
            }
        }
        return f[n-1][m-1];
    }
};

思路

  • 太简单了,dp

10.dp

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

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& o) {
        int n=o.size();
        if(!n) return 0;
        int m=o[0].size();

        vector<vector<int>> f(n,vector<int>(m));
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(!o[i][j]){
                    if(!i&&!j) f[i][j]=1;
                    else{
                        if(i) f[i][j]+=f[i-1][j];
                        if(j) f[i][j]+=f[i][j-1];
                    }
                }
            }
        }
        return f[n-1][m-1];
    }
};

思路

  • 和上一题一样
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值