力扣437+2017

题目一

力扣:2017

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

思路

1、这个题别看说的花花,总结一下,就是每个机器人只能向下走,或者向右走,因为只有两行,所以这个题就转化成了,我一直在第一行往右走,我去选择一下何时向下走,到第二行去向右走,这样一个问题。
2、一定要读好题,机器人1很坏,读好题,他的目的并不是得分最高,而是让机器人2得分最低。
3、机器人2的目的很纯粹,就是要最高分,一定要把两个机器人的策略搞清楚。所以在求第一个机器人策略的时候就不能之贪心最大分值,因为这不一定能保证机器人2得分最少
4、
在这里插入图片描述

代码:

注意
1、再求最大值的时候,初始值一般是要小于可能的目标答案,求最小值的时候,初始值一定是大于目标答案,所以一定注意对初始值的关注,一定要分析好该题答案的可能范围,初始值一定要设置好,否则会出错。
2、因为需要快速求区间和,所以用区间上的一维前缀和技术,在O(1)内求出答案

class Solution {
public:

	long long tmp[2][50005] = {};//存前缀和
	vector<vector<int>> item;//临时表格
	long long n = 0;

	long long find_path() {
		for (long long i = 1; i <= n; i++) {
			tmp[0][i] = item[0][i - 1];
			tmp[1][i] = item[1][i - 1];
		}
		for (long long i = 1; i <= n; i++) {//求前缀和
			tmp[0][i] += tmp[0][i - 1];
			tmp[1][i] += tmp[1][i - 1];
		}
		long long ans = LONG_MAX;//这里一定要注意,答案是long long类型,远超过int最大值,所以这里用long 的最值来作为初始值,保证一定大于答案
		for (long long i = 1; i <= n; i++) {
			long long tmp1 = tmp[0][n] - tmp[0][i];//求两个段
			long long tmp2 = tmp[1][i - 1] - tmp[1][0];
			ans = min(ans, max(tmp1, tmp2));//满足两个机器人各自的需求
		}
		return ans;
	}

	long long gridGame(vector<vector<int>>& grid) {
		item = grid;
		n = grid[0].size();
		return find_path();
	}
};



(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述

时间复杂度:O(N)

题目二(9月28号每日一题)

力扣:437
在这里插入图片描述

思路

(今天只介绍DFS的算法,树上前缀和算法明天在介绍).
其实这个题很明显,需要把任意一个非叶子节点当成根节点,把对应的子树搜一遍,所以很明显了,暴力解法就是递归嵌套递归就行,一个递归所检索所有节点,一个递归找对应子树有多少个合法路径。这里分为两个方向,由上向下和回溯。

自顶至底的DFS

我就是从根节点开始向下走,边走边记录已经加好的和,一旦碰到满足的节点了,在全局记录答案的地方++即可,走到空节点截止。

回溯的DFS

1、这个就是先走到最后再回过头来逐层向上进行统计,想好这种方法只需要想任意一个特殊节点就行,假设到了节点a,此时目标是找到和是targetSum,因为这里是统计路径和,走到了节点a,,所以加上了a,那么给他的子节点剩下的值为targetSum-a.val,这样,他就要问一问他的左右儿子,你们那两个分支中有多少个和为targetSum-a.val的串,获得个数之后,看看自己能不能匹配上targetSum,匹配上了,说明从上面到自己这里,恰好是一个答案,所以个数++。
2、说了这么多,其实就是针对某个子树,按照树上的节点先从上到下按照每个节点的val,瓜分targetSum,到了最底下,往回看,如果当前节点正好匹配上了分给他的targetSum,说明肯定匹配到了串,就这样回溯计算。

代码

自顶至底的DFS

class Solution {
public:
	int ans = 0;
	void finding(TreeNode* root, int sums, int target) {//sums在记录每一条路径的和
		if (root == nullptr) {
			return;
		}
		int item = sums + root->val;
		if (item == target) {
			ans++;
		}
		finding(root->left, item, target);
		finding(root->right, item, target);
	}

	void go(TreeNode* root, int target) {
		if (root == nullptr) {
			return;
		}
		finding(root, 0, target);
		go(root->left, target);
		go(root->right, target);
	}
	int pathSum(TreeNode* root, int targetSum) {
		go(root, targetSum);
		return ans;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述
时间复杂度O(N^2)
空间复杂度O(N)

回溯

class Solution {
public:
	int rootSum(TreeNode* root, int target) {
		if (root == nullptr) {
			return 0;
		}
		int ans = 0;
		ans += rootSum(root->left, target - root->val);//后根遍历用于回溯
		ans += rootSum(root->right, target - root->val);
		if (root->val == target) {
			ans++;
		}
		return ans;
	}
	int pathSum(TreeNode* root, int targetSum) {
		if (root == nullptr) {
			return 0;
		}
		
		ans += pathSum(root->left, targetSum);//后根遍历用于回溯
		ans += pathSum(root->right, targetSum);
		int ans = rootSum(root, targetSum);
		return ans;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):
在这里插入图片描述
时间复杂度O(N^2)
空间复杂度O(N)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JLU_LYM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值