力扣第 66 场双周赛

第一百零七天 --- 力扣第 66 场双周赛

  • 题目一
    • 思路
    • 代码
  • 题目二
    • 思路:贪心法
    • 代码
  • 题目三
    • 思路
    • 代码

题目一

力扣:2087. 网格图中机器人回家的最小代价

力扣第 66 场双周赛_第1张图片
力扣第 66 场双周赛_第2张图片
力扣第 66 场双周赛_第3张图片

思路

拿到题目,一定先读好题!!!!!总结一下:这就是到TM的脑筋急转弯。。。。
1、乍一看,和我们平时的机器人走路问题,很相似,一定要仔细读题呀!
2、他的代价计算规则是,走到第i行,花费rowCosts[i],一次只能走一步。那么我从当前行列直接不绕路的走到目的地,经过的行列,就是固定的
3、如果我们不那样直达,而采取非直达,上述花费一定少不了,并且还得多出到无用行列的费用
4、综上,直达费用最小。

代码

class Solution {
public:
	int minCost(vector<int>& startPos, vector<int>& homePos, vector<int>& rowCosts, vector<int>& colCosts) {
		if (startPos[0] == homePos[0] && startPos[1] == homePos[1]) {
			return 0;
		}

		int sx = startPos[0], sy = startPos[1];//起始行列
		int hx = homePos[0], hy = homePos[1];//终止行列
		int ans = 0;
		
		//行
		if (sx <= hx) {//判断是小到大还是大到小
			for (int i = sx + 1; i <= hx; i++) {
				ans += rowCosts[i];
			}
		}
		else {
			for (int i = sx - 1; i >= hx; i--) {
				ans += rowCosts[i];
			}
		}

		//列
		if (sy <= hy) {//判断是小到大还是大到小
			for (int i = sy + 1; i <= hy; i++) {
				ans += colCosts[i];
			}
		}
		else {
			for (int i = sy - 1; i >= hy; i--) {
				ans += colCosts[i];
			}
		}
		return ans;
	}
}; 

所有代码均以通过力扣测试
(经过多次测试最短时间为):
力扣第 66 场双周赛_第4张图片

题目二

力扣:2086. 从房屋收集雨水需要的最少水桶数

力扣第 66 场双周赛_第5张图片
力扣第 66 场双周赛_第6张图片
力扣第 66 场双周赛_第7张图片

思路:贪心法

1、我们要把桶放在空地上接房檐的水,并且还要桶最少,所以只有房子边上的空地有意义,如果一个房子两边都没有空地,则无解
2、同时也并不是所有房子边上的空地都要,记住我们的目的,让桶最少,所以一个桶要尽可能的发挥最大的用处
3、所以每审视一个空地他的价值的时候,如果他的两边都有房子,并且这两个房子旁边都没有水桶接,为2,反之为1,为0代表放不了。
4、最后,每一次放水桶都优先放在价值大的一侧。
5、至此,便分析完毕了。

代码

class Solution {
public:
	int minimumBuckets(string street) {
		unordered_set<int> item;//所有空地位置,放完水桶后消失
		unordered_set<int> item_H;//也是所有房子位置,用于快速匹配
		unordered_set<int> right;//已经有水桶的房屋
		vector<int> H;//存所有房子位置
		int ans = 0;

		for (int i = 0; i < street.size(); i++) {//初始化
			if (street[i] == 'H') {
				H.push_back(i);
				item_H.insert(i);
			}
			else {
				item.insert(i);
			}
		}

		for (int i = 0; i < H.size(); i++) {
			if (right.count(H[i]) == 0) {//已经有水桶的房子跳过
				ans++;
				int pos_l = H[i] - 1;//左右放水桶位置
				int pos_r = H[i] + 1;
				int cnt_l = 0;//价值
				int cnt_r = 0;
				if (item.count(pos_l) > 0) {//能放水桶
					if (item_H.count(pos_l - 1) > 0 && right.count(pos_l - 1) == 0) {//该水桶左右两侧都有未有水桶的屋子
						cnt_l = 2;
					}
					else {
						cnt_l = 1;
					}
				}
				if (item.count(pos_r) > 0) {//右侧同理
					if (item_H.count(pos_r + 1) > 0 && right.count(pos_l + 1) == 0) {
						cnt_r = 2;
					}
					else {
						cnt_r = 1;
					}
				}
				if (cnt_l == 0 && cnt_r == 0) {//两边都放不了。无解
					return -1;
				}
				else if (cnt_l > cnt_r) {//挑价值大的一边
					item.erase(pos_l);//擦除位置
					if (cnt_l == 2) {
						right.insert(H[i]);
						right.insert(H[i] - 2);
					}
					else {
						right.insert(H[i]);
					}
				}
				else {
					item.erase(pos_r);
					if (cnt_r == 2) {
						right.insert(H[i]);
						right.insert(H[i] + 2);
					}
					else {
						right.insert(H[i]);
					}
				}
			}


		}
		return ans;
	}
};

所有代码均以通过力扣测试
(经过多次测试最短时间为):
力扣第 66 场双周赛_第8张图片

题目三

力扣:2085. 统计出现过一次的公共字符串

力扣第 66 场双周赛_第9张图片
力扣第 66 场双周赛_第10张图片

思路

暴力模拟

代码

class Solution {
public:
	int countWords(vector<string>& words1, vector<string>& words2) {
		unordered_map<string, int> item1;
		unordered_map<string, int> item2;
		int ans = 0;
		for (string tmp : words1) {
			item1[tmp]++;
		}
		for (string tmp : words2) {
			item2[tmp]++;
		}
		for (int i = 0; i < words1.size(); i++) {
			if (item1[words1[i]] == 1) {
				if (item2[words1[i]] == 1) {
					ans++;
				}
			}
		}
		return ans;
	}
};

所有代码均以通过力扣测试
(经过多次测试最短时间为):
力扣第 66 场双周赛_第11张图片

你可能感兴趣的:(力扣题解,暴力法,模拟,贪心,脑筋急转弯,数组)