leetcode刷题记录(二)

墙与门

题目地址
知识点:广度优先遍历,最短路径
解题思路:最直观的解题思路是,从每一个房间分别广度优先遍历,寻找到最近的门。
但是更高效的解决方法是,从多个门同时广度遍历,就可以同时对整个图进行广度优先搜索。

#define INF 0x7fffffff
class Solution {
public:
    void wallsAndGates(vector<vector<int>>& rooms) {
        queue<vector<int>> q;
        int m = rooms.size();
        if (m < 1)
            return;
        int n = rooms[0].size();
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (rooms[i][j] == 0)
                    q.push({i, j});
        while(q.size() > 0)
        {
            int size = q.size();
            for (int i = 0; i < size; i++)
            {
                vector<int> ele = q.front();
                q.pop();
                int row = ele[0], col = ele[1];
                if (isValid(row-1, col, m, n) && rooms[row-1][col] == INF)
                {
                    rooms[row-1][col] = rooms[row][col] + 1;
                    q.push({row-1, col});
                }
                if (isValid(row+1, col, m, n) && rooms[row+1][col] == INF)
                {
                    rooms[row+1][col] = rooms[row][col] + 1;
                    q.push({row+1, col});
                }
                if (isValid(row, col-1, m, n) && rooms[row][col-1] == INF)
                {
                    rooms[row][col-1] = rooms[row][col] + 1;
                    q.push({row, col-1});
                }
                if (isValid(row, col+1, m, n) && rooms[row][col+1] == INF)
                {
                    rooms[row][col+1] = rooms[row][col] + 1;
                    q.push({row, col+1});
                }
            }
        }
    }

    bool isValid(int i, int j, int m, int n)
    {
        if (i < 0 || i >= m || j < 0 || j >= n)
            return false;
        return true;
    }
};

寻找重复数

题目地址
解题思路:

  1. 排序,如果nums[i] = nums[i-1]返回
  2. set存储,如果set中已经存在,返回
  3. 非常tricky的解决思路,解法等同于环状链表找entry point
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int fast = nums[0];
        int slow = nums[0];
        do{
            slow = nums[slow];
            fast = nums[nums[fast]];
        }while(fast != slow);
        slow = nums[0];
        while(slow != fast)
        {
            slow = nums[slow];
            fast = nums[fast];
        }
        return slow;
    }
};

【打家劫舍】全总结

题目地址
知识点:树遍历,动态规划

打家劫舍基础版

解题思路:

  1. 递归思路 + 记忆化搜索
void helper(vector<int> nums, int pos)
{
	if (pos >= nums.length)
		return 0;
	return std::max(helper(nums, pos+1), helper(nums, pos+2) + nums[i]);
	//可以把计算结果存储在一个map中防止重复计算。
}
  1. 动态规划思路
\\状态转移方程
dp[0] = nums[0];
dp[1] = std::max(dp[0], dp[1]);
dp[i] = std::max(dp[i-1], dp[i-2] + nums[i]);

打家劫舍进阶版【环形】

解题思路:分两种情况讨论,一种是抢第一家,不抢最后一家;一种是不抢第一家,抢最后一家

//动态规划思路
int cond1 = dp(nums, 1, n-1);
int cond2 = dp(nums, 0, n-2);
return std::max(cond1, cond2);
int dp(vector<int> nums, int start, int end)
{
	nums[start] = nums[start];
	nums[start+1] = std:max(nums[start], nums[start+1]);
	for (int i = start + 2; i <= end; i++)
	{
		dp[i] = std::max(dp[i-1], dp[i-2] + nums[i]);
	}
	return dp[end];
}
//递归思路
void helper(vector<int> nums, int start, int end)
{
	if (start >= end)
		return 0;
	return std::max(helper(nums, start+1, end), helper(nums, start+2, end) + nums[i]);
	//可以把计算结果存储在一个map中防止重复计算。
}

打家劫舍终极版【树形】

解题思路:
每一层递归的结果是:
爷爷节点 + 孙子节点 vs 儿子节点的最大值

using namespace std;
class Solution {
public:
    map<TreeNode*, int> m;
    int rob(TreeNode* root) {
        return helper(root);
    }

    int helper(TreeNode* root)
    {
        if (root == nullptr)
            return 0;
        if (m.find(root) != m.end())
            return m.find(root)->second;
        if (root == nullptr)
            return 0;

        int child = 0;
        int grandChild = 0;
        if (root->left != nullptr)
        {
            child += rob(root->left);
            grandChild = rob(root->left->left) + rob(root->left->right);
        }
        if (root->right != nullptr)
        {
            child += rob(root->right);
            grandChild += rob(root->right->left) + rob(root->right->right);
        }    
        int res = max(grandChild + root->val, child);
        m[root] = res;
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值