Leetcode进阶之路——Weekly Contest 143

1103. Distribute Candies to People
1103
给定两个整数,分别表示糖果数和人数,按顺序给第i个人分配i+1个糖果,若第二个循环,则给第i个人i + 1 + N个糖果
返回最后每个人拥有的糖果数
直接初始化整个数组,然后遍历一遍即可

class Solution {
public:
    vector<int> distributeCandies(int candies, int num_people) {
        vector<int> res(num_people, 0);
        int pos = 0;
        while(candies > 0)
        {
            if(pos + 1 >= candies)
            {
                res[pos % num_people] += candies;
                candies = 0;
            }
            else
            {
                res[pos % num_people] += (pos + 1);
                candies = candies - pos - 1;
            }
            pos++;
        }
        return res;
    }
};

1104. Path In Zigzag Labelled Binary Tree
1104
Zigzag的遍历方法如图所示,深度为奇数的从左往右,深度为偶数的从右往左
给定一个节点值,返回从根节点到该节点的路径
其实如果是正常的二叉树,某一个节点a与其父节点b的关系为 b = a / 2(取整)
因此这里可以先找出来该节点对应于正常的树的值,考虑到对于每一层(设深度为h),最小的元素为minn = 2h-1 , 最大的元素为maxn = 2h-1,因此先找到其在正常二叉树的对应值:n = (minn + maxn - val),然后保存n / 2即可
最后对返回值reverse翻转

class Solution {
public:
    vector<int> pathInZigZagTree(int label) {
        vector<int> res;
        while(label)
        {
            res.emplace_back(label);
            int layer = log2(label) + 1;
            int relative = pow(2, layer) - 1 + pow(2, layer - 1) - label;
            label = relative / 2;
        }
        reverse(res.begin(), res.end());
        return res;
    }
};

1105. Filling Bookcase Shelves
1105
给定一个二维数组,每个元素表示一本书的宽度和高度,shelf_width表示一个书架的宽度
将书按序放置,求最小堆叠的高度
首先注意这里是按序放置,也就是不能先放第一本书再放第三本,后放第二本
其次,这是一道动态规划的问题
对于第i + 1本书,有两种放置方法:

  • 直接放到下面新的一层,则dp[i + 1] = dp[i] + books[i + 1][1]
  • 将其尽可能多地与前面的书合并,则需要从i + 1反过来遍历,找到最多能合并的书的个数,及其对应的高度。这里“最多的书的数量”取决于这些书的宽度之和,需要小于等于shelf_width

有了这两点,就可以得到如下代码:

#define fo(i, a, b) for(int i = a; i < b; ++i)
class Solution {
public:
    int minHeightShelves(vector<vector<int>>& books, int shelf_width) {
		vector<int> dp(books.size() + 1, 0);
		fo(i, 0, books.size())
		{
			dp[i + 1] = dp[i] + books[i][1];
			int curh = 0, curw = 0;
			for (int j = i; j >= 0; --j)
			{
				curw += books[j][0];
				if (curw > shelf_width) break;
				else
				{
					curh = max(curh, books[j][1]);
					dp[i + 1] = min(dp[i + 1], dp[j] + curh);
				}
			}
		}
		return dp[books.size()];
	}
};

1106. Parsing A Boolean Expression
1106
给定一个字符串,返回运算结果
运算规则:

  • “t” 、 “f” 分别表示true 和 false
  • !(exp) 表示exp的相反值
  • &(exp1, exp2, exp3) 表示exp1、exp2、exp3等 与运算 的结果
  • |(exp1, exp2, exp3) 表示exp1、exp2、exp3等做 或运算 的结果

一看到括号就想用栈,但这道题似乎不适用,然后就是递归,举个例子:
!(&(&(f),&(!(t),&(f),|(f)),&(!(&(f)),&(t),|(f,f,t))))
开头是’!’,则相当于返回后面整个大括号里&(&(f),&(!(t),&(f),|(f)),&(!(&(f)),&(t),|(f,f,t)))的相反值
而对’&'开头的运算符,可以用一个函数将其括号内的表达式进行分解,得到
{[&(f)], [&(!(t),&(f),|(f))], [&(!(&(f)),&(t),|(f,f,t))]} 这三个子表达式
至于如何分解,可以通过括号得到所对应的层数,后面看代码即可
那么由于是与运算,即对这三个子表达式对应的结果做与运算,而子表达式的运算结果,则可以通过递归调用获得
于是代码为:

#define fo(i, a, b) for(int i = a; i < b; ++i)

class Solution {
public:
    vector<string> splitExpression(string exp)
	{
		vector<string> vs;
		// 括号层数
		int layer = 0;
		string s = "";
		fo(i, 0, exp.length())
		{
			if (exp[i] == ',' && layer == 0)
			{
				vs.emplace_back(s);
				s = "";
				continue;
			}
			s += exp[i];
			if (exp[i] == '(') layer++;
			if (exp[i] == ')') layer--;
		}
		if (s.length()) vs.emplace_back(s);
		return vs;
	}

	bool parseBoolExpr(string expression) {
		int len = expression.length();
		if (expression.length() == 1) return expression[0] == 't';
		// 若开头为!,返回其值域的作用域,作用域为expression.substr(2, len - 3)
		if (expression[0] == '!') return !parseBoolExpr(expression.substr(2, len - 3));
		vector<string> exp = splitExpression(expression.substr(2, len - 3));
		if (expression[0] == '|')
		{
			bool res = false;
			for (string s : exp)
			{
				res |= parseBoolExpr(s);
			}
			return res;
		}
		else
		{
			bool res = true;
			for (string s : exp)
			{
				res &= parseBoolExpr(s);
			}
			return res;
		}
    }
};
发布了109 篇原创文章 · 获赞 108 · 访问量 21万+

猜你喜欢

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