Leetcode进阶之路——Weekly Contest 136

37 篇文章 0 订阅

1041. Robot Bounded In Circle

On an infinite plane, a robot initially stands at (0, 0) and faces north. The robot can receive one of three instructions:
“G”: go straight 1 unit;
“L”: turn 90 degrees to the left;
“R”: turn 90 degress to the right.
The robot performs the instructions given in order, and repeats them forever.
Return true if and only if there exists a circle in the plane such that the robot never leaves the circle.
Example 1:
Input: “GGLLGG”
Output: true
Explanation:
The robot moves from (0,0) to (0,2), turns 180 degrees, and then returns to (0,0).
When repeating these instructions, the robot remains in the circle of radius 2 centered at the origin.
Example 2:
Input: “GG”
Output: false
Explanation:
The robot moves north indefinetely.
Example 3:
Input: “GL”
Output: true
Explanation:
The robot moves from (0, 0) -> (0, 1) -> (-1, 1) -> (-1, 0) -> (0, 0) -> …

题意:在原点(0, 0)有一个机器人,输入一串由“GLR”组成的字符串,G表示前行一格, L左转,R右转(注意这里左转右转之后不会往前进)判断最后机器人是否会回到原点
暴力做法,直接循环N次(当时设了50次)如果这么多次内还未回到原点,就直接输出否:

class Solution {
public:
   bool isRobotBounded(string instructions) {
		int mode = 0;
		int cnt = 0;
		map<pair<int, int>, int> mp;
		//pair<int, int> p(0, 0);
		mp[make_pair(0, 0)] = 1;
		int x = 0, y = 0;
		while (cnt < 50)
		{
			for (int i = 0; i < instructions.length(); ++i)
			{
				if (instructions[i] == 'L')
					mode++;
				else if (instructions[i] == 'R')
					mode += 3;
				else
				{
					switch (mode % 4)
					{
					case 0:
						y++;
						break;
					case 1:
						x--;
						break;
					case 2:
						y--;
						break;
					case 3:
						x++;
						break;
					default:
						break;
					}
				}
			}
			cnt++;
			pair<int, int> p = make_pair(x, y);
			if (mp[p]) return true;
			mp[p] ++;
		}
		return false;
	}
};

做法2,其实换一个角度,可以直接从一次执行后,机器人的朝向决定是否能回到原点:
若执行一次后,机器人不在原点,且朝北,那么继续执行只会让机器人越来越远离原点
而若执行一次后朝东南西:
若朝南,那么下一次执行就会回到原点
若朝东或西,则四次之后即回到原点
因此只要根据执行一次动作之后机器人的方向即可输出结果:

bool isRobotBounded(string instructions) {
		int mode = 0, dir = 0;
		int x = 0, y = 0;
        for (int i = 0; i < instructions.length(); ++i)
        {
            if (instructions[i] == 'L')
                mode++, dir++;
            else if (instructions[i] == 'R')
                mode += 3;
            else
            {
                switch (mode % 4)
                {
                case 0:
                    y++;
                    break;
                case 1:
                    x--;
                    break;
                case 2:
                    y--;
                    break;
                case 3:
                    x++;
                    break;
                default:
                    break;
                }
            }
        }
        return (x == 0 && y== 0) || mode % 4;
	}

1042. Flower Planting With No Adjacent

You have N gardens, labelled 1 to N. In each garden, you want to plant one of 4 types of flowers.
paths[i] = [x, y] describes the existence of a bidirectional path from garden x to garden y.
Also, there is no garden that has more than 3 paths coming into or leaving it.
Your task is to choose a flower type for each garden such that, for any two gardens connected by a path, they have different types of flowers.
Return any such a choice as an array answer, where answer[i] is the type of flower planted in the (i+1)-th garden. The flower types are denoted 1, 2, 3, or 4. It is guaranteed an answer exists.
Example 1:
Input: N = 3, paths = [[1,2],[2,3],[3,1]]
Output: [1,2,3]
Example 2:
Input: N = 4, paths = [[1,2],[3,4]]
Output: [1,2,1,2]
Example 3:
Input: N = 4, paths = [[1,2],[2,3],[3,4],[4,1],[1,3],[2,4]]
Output: [1,2,3,4]

题意精简:N个点,以及M条线,保证每条线两端的点颜色不同,输出一种可以的涂色方案(最多四种颜色)
用哈希表存储每个点的连线,由于必定有解,因此直接令第一个点的颜色为1号,之后遍历保证不冲突即可(本质其实就是DFS):

class Solution {
public:
    vector<int> gardenNoAdj(int N, vector<vector<int>>& paths) {
		map<int, vector<int>> mv;
		for (auto path : paths)
		{
			mv[path[0]].emplace_back(path[1]);
			mv[path[1]].emplace_back(path[0]);
		}
		vector<int> res(N, 0);
		res[0] = 1;
		gardenHelper(res, mv, 2, N - 1, N);
		return res;
	}

	bool gardenHelper(vector<int>& res, map<int, vector<int>>& mv, int cur, int cnt, int N)
	{
		if (cnt == 0) return true;
		vector<int> vis(5, 0);
		vector<int> v = mv[cur];
		for (int i = 0; i <v.size(); ++i)
		{
			if (res[v[i] - 1]) vis[res[v[i] - 1]]++;
		}
		for (int i = 1; i < 5; ++i)
		{
			if (vis[i] == 0)
			{
				res[cur - 1] = i;
				if (gardenHelper(res, mv, cur + 1, cnt - 1, N))
					return true;
			}
		}
		return false;
	}
};

1043. Partition Array for Maximum Sum

Given an integer array A, you partition the array into (contiguous) subarrays of length at most K. After partitioning, each subarray has their values changed to become the maximum value of that subarray.
Return the largest sum of the given array after partitioning.
Example 1:
Input: A = [1,15,7,9,2,5,10], K = 3
Output: 84
Explanation: A becomes [15,15,15,9,10,10,10]

给定一个整型数组,将其拆分成若干子串,每个子串长度最大为K,且拆分后每个子串的元素均由该子串中最大值替代,求所有拆分中所得和最大的
典型的DP,用一个数组vector dp存储结果,dp[i]表示从A[0] ~ A[i - 1]的最大和,复杂度O(NK)

class Solution {
public:
    int maxSumAfterPartitioning(vector<int>& A, int K) {
		int len = A.size();
		if (len == 0) return 0;
 		vector<int> dp(len + 1, 0);
        // dp[0] = A[0];
		for (int i = 1; i <= len; ++i)
		{
			int maxi = 0;
			for (int j = i - 1; j >= 0; --j)
			{
				maxi = max(maxi, A[j]);
				if (i - j > K) break;
				dp[i] = max(dp[i], dp[j] + (i - j) * maxi);
			}
		}
		return dp[len];
	}
};

1044. Longest Duplicate Substring

Given a string S, consider all duplicated substrings: (contiguous) substrings of S that occur 2 or more times. (The occurrences may overlap.)
Return any duplicated substring that has the longest possible length. (If S does not have a duplicated substring, the answer is “”.)
Example 1:
Input: “banana”
Output: “ana”
Example 2:
Input: “abcd”
Output: “”

给定一个字符串,找出其中最长的重复字符串
用到了Rabin-Karp + Binary Search
前一个跟KMP一样是经常用于字符串匹配的算法,将字符串用hash值代替,虽然速度上不能令人满意,但大大减小了空间消耗
二分主要用于最长重复子串长度的限制,在一定程度上弥补了时间开销

class Solution {
public:
	string longestDupSubstring(string S) {
		int low = 0, high = S.length();
		int startPos = 0, len = 0;
		while (low <= high)
		{
			int mid = (low + high) / 2;
			int start = longestDupSubstringHelper(S, mid);
			if (start != -1)
			{
				startPos = start, len = mid;
				low = mid + 1;
			}
			else
			{
				high = mid - 1;
			}
		}
		return S.substr(startPos, len);
	}

	int longestDupSubstringHelper(string S, int mid)
	{
		unsigned long long tar = 0, base = 1;
		for (int i = 0; i < mid; ++i)
		{
			tar = tar * 26 + (S[i] - '0');
			base *= 26;
		}

		set<unsigned long long> s;
		s.insert(tar);

		for (int j = mid; j < S.length(); ++j)
		{
			tar = tar * 26 + (S[j] - '0' - (S[j - mid] - '0') * base);
			if (s.find(tar) != s.end())
				return j - mid + 1;
			s.insert(tar);
		}
		return -1;
	}
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值