【刷爆LeetCode】五月算法集训(15)深度优先搜索

题目来源于知识星球—英雄算法联盟,五月算法集训专题

前言

跟随英雄算法联盟博主—英雄哪里出来,每天完成相应的算法练习,一个月后,必定会有所成长!


一、565.数组嵌套(中等)

1.题目描述

https://img-blog.csdnimg.cn/9228089a7fce408c9bef9d20774f271b.jpeg =500x

2.解题思路

想象成N个节点,每个节点都有一条出边,采用染色法,遍历所有节点,将没被
染色的节点进行访问并计数,得到计数的最大值。

3.代码演示(C++)

class Solution 
{
    int Max, Cnt;
    int hash[200010];
    void dfs(vector<int>& nums, int u, int color) 
    {
        if(hash[u] != -1) 
        {
            return ;
        }
        hash[u] = color;
        ++Cnt;
        dfs(nums, nums[u], color);
    }
public:
    int arrayNesting(vector<int>& nums) 
    {
        int i;
        int n = nums.size();
        int color = 0;
        Max = 0;
        memset(hash, -1, sizeof(hash));
        for(i = 0; i < n; ++i) 
        {
            if(-1 == hash[i]) 
            {
                Cnt = 0;
                dfs(nums, i, ++color);
                Max = max(Max, Cnt);
            }
        }
        return Max;
    }
};

4.题目链接

题目传送门


二、401.二进制手表(简单)

1.题目描述

https://img-blog.csdnimg.cn/2d4646142b14485bbfd589dec0946081.jpeg =500x

2.解题思路

共有10个位置,每个位置都是选或不选,枚举所有情况,分别记录时间,
转换成字符串。

3.代码演示(C++)

class Solution 
{
    vector<string> ans;
    int stk[10], top;
    int hv[4] = 
    {
        8, 4, 2, 1
    };
    int mv[6] = 
    {
        32, 16, 8, 4, 2, 1
    };

    string totime(int h, int m) 
    {
        string ans = "";
        if(h <= 9) 
        {
            ans += h + '0';
        }
        else 
        {
            ans += h/10 + '0';
            ans += h % 10 + '0';
        }
        ans += ":";
        ans += m/10 + '0';
        ans += m%10 + '0';
        return ans;
    }

    void dfs(int deng, int maxDeng, int light, int maxLight) 
    {
        if(deng == maxDeng) 
        {
            if(light == maxLight) 
            {
                int h = 0, m = 0;
                for(int i = 0; i < top; ++i) 
                {
                    int x = stk[i];
                    if(x <= 3) 
                    {
                        h += hv[x];
                    }
                    else 
                    {
                        m += mv[x-4];
                    }
                }
                if(h <= 11 && m <= 59) 
                {
                    ans.push_back( totime(h, m) );
                }
            }
            return ;
        }  
        if(light > maxLight) 
        {
            return ;
        } 

        dfs(deng+1, maxDeng, light, maxLight);
        stk[top++] = deng;
        dfs(deng+1, maxDeng, light + 1, maxLight);
        --top;
    }

public:
    vector<string> readBinaryWatch(int turnedOn) 
    {
        top = 0;
        ans.clear();
        dfs(0, 10, 0, turnedOn);
        return ans;
    }
};

4.题目链接

题目传送门


三、1079.活字印刷(中等)

1.题目描述

https://img-blog.csdnimg.cn/43544a780b9f4ca1b4642362deeb23da.jpeg =500x

2.解题思路

枚举一个长度,再枚举长度对应的元素的全排列,利用字符串进行判断计数。

3.代码演示(C++)

class Solution 
{
    unordered_map<string, bool> rethash;
    bool visited[26];
    char stk[10], top;
    int cnt;
    void dfs(string& tiles, int depth, int maxDepth) 
    {
        if(depth == maxDepth) 
        {
            stk[top] = '\0';
            if(rethash.find(stk) == rethash.end()) 
            {
                rethash[stk] = true;
                ++cnt;
            }
            return ;
        }
        int i, n = tiles.size();
        for(i = 0; i < n; ++i) 
        {
            if(!visited[i]) 
            {
                visited[i] = true;
                stk[top++] = tiles[i];
                dfs(tiles, depth + 1, maxDepth);
                --top;
                visited[i] = false;
            }
        }
    }

public:
    int numTilePossibilities(string tiles) 
    {
        int i;
        rethash.clear();
        memset(visited, false, sizeof(visited));
        cnt = 0;
        top = 0;
        for(i = 1; i <= tiles.size(); ++i) 
        {
            dfs(tiles, 0, i);
        }
        return cnt;
    }
};

4.题目链接

题目传送门


四、1219.黄金矿工(中等)

1.题目描述

https://img-blog.csdnimg.cn/173198a222ce48e0aa327999697ed022.jpeg =500x

2.解题思路

枚举一个可能有金矿的位置,枚举四个方向,判断边界和障碍,再递归调用,
找到最长路即可。

3.代码演示(C++)

class Solution 
{
    int hash[16][16];
    int maxv;
    int dir[4][2] = 
    {
        {0, 1}, {1, 0}, {0, -1}, {-1, 0}
    };
    void dfs(vector<vector<int>>& grid, int m, int n, int x, int y, int sum) 
    {
        maxv = max(maxv, sum);
        for(int i = 0; i < 4; ++i) 
        {
            int tx = x + dir[i][0];
            int ty = y + dir[i][1];
            if(tx < 0 || ty < 0 || tx == m || ty == n) 
            {
                continue;
            }
            if(grid[tx][ty] == 0) 
            {
                continue;
            }
            if(!hash[tx][ty]) 
            {
                hash[tx][ty] = 1;
                dfs(grid, m, n, tx, ty, sum + grid[tx][ty]);
                hash[tx][ty] = 0;
            }  
        }
    }
public:
    int getMaximumGold(vector<vector<int>>& grid) 
    {
        int n, m;
        int i, j;
        int ret = 0;
        memset(hash, 0, sizeof(hash));
        m = grid.size();
        n = grid[0].size();
        for(i = 0; i < m; ++i) 
        {
            for(j = 0; j < n; ++j) 
            {
                if(grid[i][j]) 
                {
                    hash[i][j] = 1;
                    maxv = 0;
                    dfs(grid, m, n, i, j, grid[i][j]);
                    ret = max(ret, maxv);
                    hash[i][j] = 0;
                }
            }
        }
        return ret;
    }
};

4.题目链接

题目传送门


总结

每天跟随英雄哥学习相关的算法,一个月会收获很多,如果你想了解更多关于知识星球的内容,欢迎联系我!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值