Leetcode进阶之路——Weekly Contest 133

37 篇文章 0 订阅

1029 Two City Scheduling

here are 2N people a company is planning to interview. The cost of flying the i-th person to city A is costs[i][0], and the cost of flying the i-th person to city B is costs[i][1].
Return the minimum cost to fly every person to a city such that exactly N people arrive in each city.
Example 1:
Input: [[10,20],[30,200],[400,50],[30,20]]
Output: 110
Explanation:
The first person goes to city A for a cost of 10.
The second person goes to city A for a cost of 30.
The third person goes to city B for a cost of 50.
The fourth person goes to city B for a cost of 20.
The total minimum cost is 10 + 30 + 50 + 20 = 110 to have half the people interviewing in each city.

题意给定一个二维向量,每个元组包含两个元素,第一个表示飞到城市A需要的花费,第二个元素表示飞到城市B需要的花费,向量大小为2N,若城市A和B正好各有N个人,求最小花费是多少
这道题先自己列几个情况,就可以大致得出结论:飞到两个城市的花费差值越小,则选择飞到哪个城市对整体的影响越小,因此先将差值大的安排了,之后安排差值小的
比如 [40, 50], [5, 35],如果按顺序选择花费小的,那第一个就选择了城市A,第二个只能选择城市B,总花费为75
但实际第一个只差了10,对整体花费影响相对较小,应先让第二个人进行选择,则为5+50=55
于是可以先按照两者的差值从大到小进行排序,然后安排各自城市

class Solution {
public:
    static bool twocitycmp(vector<int> &v1, vector<int> & v2)
	{
		if (abs(v1[0] - v1[1]) > abs(v2[0] - v2[1])) return true;
		return false;
	}

	int twoCitySchedCost(vector<vector<int>>& costs) {
		int len = costs.size();
		if (len == 0) return 0;
		int sum = 0;
		// sorted by difference
		sort(costs.begin(), costs.end(), twocitycmp);
		int a = 0, b = 0;
		for (auto v : costs)
		{
			if (a == len / 2) sum += v[1];
			else if (b == len / 2) sum += v[0];
			else
			{
				if (v[0] < v[1])
				{
					a++;
					sum += v[0];
				}
				else
				{
					b++;
					sum += v[1];
				}
			}
		}
		return sum;
	}
};

1030. Matrix Cells in Distance Order

We are given a matrix with R rows and C columns has cells with integer coordinates (r, c), where 0 <= r < R and 0 <= c < C.
Additionally, we are given a cell in that matrix with coordinates (r0, c0).
Return the coordinates of all cells in the matrix, sorted by their distance from (r0, c0) from smallest distance to largest distance. Here, the distance between two cells (r1, c1) and (r2, c2) is the Manhattan distance, |r1 - r2| + |c1 - c2|. (You may return the answer in any order that satisfies this condition.)
Example 1:
Input: R = 1, C = 2, r0 = 0, c0 = 0
Output: [[0,0],[0,1]]
Explanation: The distances from (r0, c0) to other cells are: [0,1]
Example 2:
Input: R = 2, C = 2, r0 = 0, c0 = 1
Output: [[0,1],[0,0],[1,1],[1,0]]
Explanation: The distances from (r0, c0) to other cells are: [0,1,1,2]
The answer [[0,1],[1,1],[0,0],[1,0]] would also be accepted as correct.
Example 3:
Input: R = 2, C = 3, r0 = 1, c0 = 2
Output: [[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]]
Explanation: The distances from (r0, c0) to other cells are: [0,1,1,2,2,3]
There are other answers that would also be accepted as correct, such as [[1,2],[1,1],[0,2],[1,0],[0,1],[0,0]].

给定行数和列数,以及初始坐标(r0, c0),按照距离初始坐标距离升序给出坐标点的集合
乍一看是典型的广度优先搜索,相应代码:

class Solution {
public:
    vector<vector<int>> allCellsDistOrder(int R, int C, int r0, int c0) {
		vector<vector<int>> visited(R, vector<int>(C, 0));
		queue<vector<int>> q;
		int x = r0, y = c0;
		vector<vector<int>> res;
		vector<int> v = { x, y };
		q.emplace(v);
		visited[x][y] = 1;
		// bfs
		while (!q.empty())
		{
			int cnt = q.size();
			for (int i = 0; i < cnt; ++i)
			{
				vector<int> v = q.front();
                q.pop();
				res.emplace_back(v);
				x = v[0], y = v[1];
				if (x + 1 < R && !visited[x + 1][y])
				{
					visited[x + 1][y] = 1;
					vector<int> vec = { x + 1, y };
					q.emplace(vec);
				}
				if (y + 1 < C && !visited[x][y + 1])
				{
					visited[x][y + 1] = 1;
					vector<int> vec = { x, y + 1 };
					q.emplace(vec);
				}
				if (x - 1 >= 0 && !visited[x - 1][y])
				{
					visited[x - 1][y] = 1;
					vector<int> vec = { x - 1, y };
					q.emplace(vec);
				}
				if (y - 1 >= 0 && !visited[x][y - 1])
				{
					visited[x][y - 1] = 1;
					vector<int> vec = { x, y - 1 };
					q.emplace(vec);
				}
			}
		}
		return res;
	}
};

然而其实对STL了解的话,直接用sort就可以解决:

class Solution {
public:
    vector<vector<int>> allCellsDistOrder(int R, int C, int r0, int c0) {
		vector<vector<int>> res(R * C, vector<int>(2, 0));
		for(int i = 0; i < R; ++i)
        {
            for(int j = 0; j < C; ++j)
            {
                res[i*C+j][0] = i;
                res[i*C+j][1] = j;
            }
        }
        
        sort(res.begin(), res.end(), 
             [&](const vector<int>& v1, const vector<int>& v2)
             {
                 return abs(v1[0]-r0) + abs(v1[1] - c0) < abs(v2[0] - r0) + abs(v2[1] - c0);
             });
		return res;
	}
};

1031. Maximum Sum of Two Non-Overlapping Subarrays

Given an array A of non-negative integers, return the maximum sum of elements in two non-overlapping (contiguous) subarrays, which have lengths L and M. (For clarification, the L-length subarray could occur before or after the M-length subarray.)
Formally, return the largest V for which V = (A[i] + A[i+1] + … + A[i+L-1]) + (A[j] + A[j+1] + … + A[j+M-1]) and either:
0 <= i < i + L - 1 < j < j + M - 1 < A.length, or
0 <= j < j + M - 1 < i < i + L - 1 < A.length.
Example 1:
Input: A = [0,6,5,2,2,5,1,9,4], L = 1, M = 2
Output: 20
Explanation: One choice of subarrays is [9] with length 1, and [6,5] with length 2.
Example 2:
Input: A = [3,8,1,3,2,1,8,9,0], L = 3, M = 2
Output: 29
Explanation: One choice of subarrays is [3,8,1] with length 3, and [8,9] with length 2.
Example 3:
Input: A = [2,1,5,6,0,9,5,0,3,8], L = 4, M = 3
Output: 31
Explanation: One choice of subarrays is [5,6,0,9] with length 4, and [3,8] with length 3.

给定一个数组,找出其中连续且不重叠的的L个和M个子数组,使其和最大
这道题给的时间很宽,直接暴力O(N 2 )也可以Accept
但是其实这个完全可以先把到当前下标的最大子串和保存下来,再用一轮循环遍历求解
由于题目说了L在前和M在前都是合法的,因此进行两轮即可

class Solution {
public:
    int maxSumTwohelper(vector<int>& A, int L, int M)
	{
		vector<int> vl(A.size(), 0), vm(A.size(), 0);
		int sum1 = 0, sum2 = 0;
		for (int i = 0, j = A.size() - 1; i < A.size(); ++i, --j)
		{
			sum1 += A[i];
			sum2 += A[j];
            vl[i] = sum1;
			vm[j] = sum2;
			if (i >= L - 1)
			{
				if (i == 0) vl[i] = sum1;
				else vl[i] = max(vl[i - 1], sum1);
				sum1 -= A[i - L + 1];
			}
			if (j <= A.size() - M)
			{
				if (j == A.size() - 1) vm[j] = sum2;
				else vm[j] = max(vm[j + 1], sum2);
				sum2 -= A[j + M - 1];
			}
		}

		int res = 0;
		for (int i = L - 1; i < A.size() - M; ++i)
		{
			res = max(res, vl[i] + vm[i + 1]);
		}
		return res;
	}
	int maxSumTwoNoOverlap(vector<int>& A, int L, int M) {
		
		return max(maxSumTwohelper(A, L, M), maxSumTwohelper(A, M, L));
	}
};

1032. Stream of Characters

Implement the StreamChecker class as follows:
StreamChecker(words): Constructor, init the data structure with the given words.
query(letter): returns true if and only if for some k >= 1, the last k characters queried (in order from oldest to newest, including this letter just queried) spell one of the words in the given list.
Example:
StreamChecker streamChecker = new StreamChecker([“cd”,“f”,“kl”]); // init the dictionary.
streamChecker.query(‘a’); // return false
streamChecker.query(‘b’); // return false
streamChecker.query(‘c’); // return false
streamChecker.query(‘d’); // return true, because ‘cd’ is in the wordlist
streamChecker.query(‘e’); // return false
streamChecker.query(‘f’); // return true, because ‘f’ is in the wordlist
streamChecker.query(‘g’); // return false
streamChecker.query(‘h’); // return false
streamChecker.query(‘i’); // return false
streamChecker.query(‘j’); // return false
streamChecker.query(‘k’); // return false
streamChecker.query(‘l’); // return true, because ‘kl’ is in the wordlist

先给一个字符串数组,之后每次Query都判断以当前字符结尾的连续字符串,在前面的字符串数组中是否出现过
也是一道很典型的字典树,用一个exist标识来判断到目前为止的字符串是否在初始化数组中出现过

struct node
{
    bool exist;
    node* next[26];
    node()
    {
        exist = false;
        memset(next, 0, sizeof(next));
    }
};
class StreamChecker {
    node* root;
    string s;
public:
    StreamChecker(vector<string>& words) {
        s = "";
		root = new node();
        for(string w: words)
        {
            node* n = root;
            int len = w.length();
            for(int i = len - 1; i >= 0; --i)
            {
                if(n->next[w[i] - 97] == NULL) n->next[w[i] - 97] = new node();
                n = n->next[w[i] - 97];
            }
            n->exist = true;
        }
    }
    
    bool query(char letter) {
        s += letter;
        if(root->next[letter - 97] == NULL) return false;
        node* n = root;
        for(int i = s.length() - 1; i >= 0; --i)
        {
            if(n == NULL) return false;
            if(n->exist) return true;
            n = n->next[s[i] - 97];
        }
        if (n == NULL) return false;
		else return n->exist;
    }
};

/**
 * Your StreamChecker object will be instantiated and called as such:
 * StreamChecker* obj = new StreamChecker(words);
 * bool param_1 = obj->query(letter);
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值