Leetcode进阶之路——Weekly Contest 146

1128. Number of Equivalent Domino Pairs
1128
给定一个二维数组,判断其中相同元素的个数
相同元素的定义:
若对于下标i、j,有dominoes[i] = [a, b], dominoes[j]=[c, d]
若a=c且b=d 或者 a=d且b=c,则可判断dominoes[i] = dominoes[j]
因此思路先遍历原数组,使得数字小的在前,后用一个哈希表保存每个元素出现的次数,最后取 C n 2 C_n^2 即可:

class Solution {
public:
    int numEquivDominoPairs(vector<vector<int>>& dominoes) {
        for(int i = 0; i < dominoes.size(); ++i)
        {
            if(dominoes[i][0] > dominoes[i][1])
            {
                dominoes[i][0] ^= dominoes[i][1];
                dominoes[i][1] ^= dominoes[i][0];
                dominoes[i][0] ^= dominoes[i][1];
            }
        }
        sort(dominoes.begin(), dominoes.end());
        map<vector<int>, int> m;
        for(auto v: dominoes)
            m[v]++;
        int res = 0;
        for(auto v: m)
            if(v.second > 1) res += (v.second * (v.second - 1)) / 2;
        return res;
    }
};

1129. Minimum Cost Tree From Leaf Values
1129
一个数组表示树的叶子节点,且按照中序遍历给定,非叶节点的值为其左右子树中,最大的两个叶节点的乘积(非叶节点仅有0或2个儿子节点)
重构这棵树,使得所有非叶节点的和最小
直接贪心,由于原数组符合中序遍历,因此每次遍历,取其中相邻元素乘积最小的结合,之后这两个元素中的较小值就再也不会用到,因此直接删除,循环该过程直到仅有一个元素

class Solution {
public:
    int mctFromLeafValues(vector<int>& arr) {
		int res = 0;
		while (arr.size() > 1)
		{
			int minn = 1e9, pos = 0;
			for(int i = 0; i < arr.size() - 1; ++i)
				if (arr[i] * arr[i + 1] < minn)
				{
					minn = arr[i] * arr[i + 1];
					if (arr[i] > arr[i + 1]) pos = i + 1;
					else pos = i;
				}
			res += minn;
			vector<int>::iterator it = arr.begin() + pos;
			arr.erase(it);
		}
		return res;
	}
};

1130. Shortest Path with Alternating Colors
1130
给定一个整数代表节点数,两个二维数组,red_edges表示连接两个顶点的边为红边,blue_edges表示连接两个顶点的边为蓝边,判断从节点0到节点n的最短路径,满足该路径中红蓝边交替出现
是个典型的bfs,保存每条边的邻接边(有向图)及其颜色(我这里1代表红色,2代表蓝色),每次遍历使判断颜色是否与前一条边不同
还要注意:

  1. 无论什么情况,0号节点对应的路径长都为0,但测试样例中存在[0, 0]边,即自环,应忽略
  2. 可能存在一条边既是红边又是蓝边,这时当存在环时,可能有区别:
    1
    这时节点4在经过了一个环之后才能按规则访问到,我的代码可能有点冗余
class Solution {
public:
    vector<int> shortestAlternatingPaths(int n, vector<vector<int>>& red_edges, vector<vector<int>>& blue_edges) {
		queue<pair<int, int>> q;
		vector<int> res(n, -1);
		
		sort(red_edges.begin(), red_edges.end());
		sort(blue_edges.begin(), blue_edges.end());
		unordered_map<int, vector<pair<int, int>>> hash;
		// second=1: red;  second=2: blue
		for (auto v : red_edges)
		{
			hash[v[0]].emplace_back(make_pair(v[1], 1));
			if (v[0] == 0)
			{
				q.emplace(make_pair(v[1], 1));
				res[v[1]] = 1;
			}
		}
		for (auto v : blue_edges)
		{
			hash[v[0]].emplace_back(make_pair(v[1], 2));
			if (v[0] == 0) 
			{
				q.emplace(make_pair(v[1], 2));
				res[v[1]] = 1;
			}
		}
        res[0] = 0;
		int step = 1;
		while (!q.empty())
		{
			step++;
			unsigned cnt = q.size();
			queue<pair<int, int>> tmp;
			while (!q.empty())
			{
				pair<int, int> p = q.front();
				q.pop();
				for (int i = 0; i < hash[p.first].size(); ++i)
				{
					pair<int, int> v = hash[p.first][i];
					if (v.first == -1) continue;
					if (v.second != p.second)
					{
						if(res[v.first] < 0) res[v.first] = step;
						tmp.emplace(make_pair(v.first, v.second));
						hash[p.first][i].first = -1;
					}
				}
			}
			q = tmp;
		}
		return res;
	}
};

1131. Maximum of Absolute Value Expression
1131
给定两个数组,返回|arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j|中的最大值
对于两个数组,各有两个取值(正负),因此直接循环四次,取每次最大、最小值之差即可得到结果

class Solution {
public:
    int maxAbsValExpr(vector<int>& arr1, vector<int>& arr2) {
        int sign[2] = {-1, 1};
        int res = 0, size = arr1.size();
        for(int m: sign)
            for(int n: sign)
            {
                int maxn = 0, minn = INT_MAX;
                for(int i = 0; i < size; ++i)
                {
                    int tmp = arr1[i] * m + arr2[i] * n + i;
                    minn = min(minn, tmp);
                    maxn = max(maxn, tmp);
                }
                res = max(res, maxn - minn);
            }
        return res;
    }
};
发布了109 篇原创文章 · 获赞 108 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/u013700358/article/details/96708143