1609. 奇偶树 #广搜 #二叉树的层次遍历

题目链接

题意

如果一棵二叉树满足下述几个条件,则可以称为奇偶树 :

  • 二叉树根节点所在层下标为 0 ,根的子节点所在层下标为 1 ,根的孙节点所在层下标为 2 ,依此类推。

  • 偶数下标 层上的所有节点的值都是 奇 整数,从左到右按顺序 严格递增

  • 奇数下标 层上的所有节点的值都是 偶 整数,从左到右按顺序 严格递减

给定根节点,要求判断该二叉树是否为奇偶树

分析

BFS对于已知根节点,按深度遍历时,十分高效。这里要注意下入队列顺序是从左至右。

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isEvenOddTree(TreeNode* root) {
queue<TreeNode*> myque;
myque.push(root);
int depth = 0;
while (!myque.empty()) {
int n = myque.size();
TreeNode* pre = nullptr, * cur = nullptr;//pre节点为与cur同高的左边节点
while (n--) { //将当前高度的所有节点都遍历一次
cur = myque.front(); myque.pop();
if (depth & 1) {
if (cur->val & 1) return false;
if (pre != nullptr && pre->val <= cur->val) return false;
}
else {
if (cur->val % 2 == 0) return false;
if (pre != nullptr && pre->val >= cur->val) return false;
}
if (cur->left) myque.push(cur->left);
if (cur->right) myque.push(cur->right);
pre = cur;
}
depth++;
}
return true;
}
};

1610. 可见点的最大数目 #极角 #排序 #双指针

题目链接

题意

你的位置为\((pos_x, pox_y)\),视野角度为\(angle\)。现给定一组顶点坐标\(points\)。现问你的视野中最多能看到多少个顶点。

样例

分析

感谢@前额叶没长好的讲解!

atan2(y, x)函数,取值范围为\((-\pi, +\pi]\)(你可以理解为,极径从\(-\pi\)弧度逆时针旋转至\(\pi\)弧度)。当函数返回值为正,即表示从\(x\)轴逆时针旋转的弧度,返回值为负,表示从\(x\)轴顺时针旋转的弧度。atan2(y,x)与\(arctan(y/x)\)的关系如下:

\[atan2(y,x)=\begin{cases}
arctan(\frac{y}{x}) &第一象限或第四象限的点 \\
\pi+arctan(\frac{y}{x}) &第二象限的点 \\
arctan(\frac{y}{x}) &第三象限的点 \\
+\frac{\pi}{2} &y>0且x=0 \\
-\frac{\pi}{2} &y<0且x=0
\end{cases}
\]

由此我们便可利用atan2(y,x)计算\((y,x)\)的极角了,我们把点集\(points\)所有点的极角(此时为角度制)都存到一个数组中,对其从小到大排序后,每个弧度代表的点的顺序恰好\(xoy\)平面的逆时针方向,为:第三象限->第四象限->第一象限->第四象限。接着,我们通过双指针,便能找到给定区间\(angle\)下的最多点数。

但是注意,我们要求的是区间实际是一个环,还要考虑到下图中的弧\(ab\),如果直接逆时针从小到大遍历的话,就无法覆盖第二象限与第三象限之间的劣弧\(ab\)了。我们不妨再给极角数组中所有点\(+360^{\circ}\),这样就能将圆环的首尾相连了。由于我们用的是双指针,不会将之前的点重复计入。

另外,建议将角度换算为角度制而不是弧度制,弧度制太小了,容易出现精度问题(wa了8发)

const double EPS = 1e-8;
class Solution {
public:
int visiblePoints(vector<vector<int>>& points, int angle, vector<int>& location) {
vector<double> pangle;
int cnt = 0, ans = 0;
for (int i = 0; i < points.size(); i++){
double dx = location[0] - points[i][0], dy = location[1] - points[i][1];
if(dx == 0 && dy == 0) //有可能该点与位置点重合
cnt++;
else{
double tmp = 180 * atan2(dy, dx) / acos(-1.0); //求极角
pangle.push_back(tmp);
pangle.push_back(tmp + 360);
}
}
sort(pangle.begin(), pangle.end());
double ang = angle; int hi = 1;
for (int lo = 0; lo < pangle.size(); lo++){
while(hi < pangle.size() &&
(pangle[hi] - pangle[lo] < angle + EPS))
hi++;
ans = max(ans, hi - 1 - lo + 1);
}
return ans + cnt;
}
};

1611. 使整数变为0的最少操作次数 #记忆化搜索 #格雷码

题目链接

题意

给定整数$ n$,你需要重复执行多次下述操作将其转换为\(0\) :

  • 翻转$ n $的二进制表示中最右侧位(第\(0\)位)。

  • 如果第$ (i-1) \(位为\) 1 \(且从第\) (i-2) \(位到第\) 0 \(位都为\) 0\(,则翻转\) n \(的二进制表示中的第\) i $位。

返回将 \(n\) 转换为$ 0 $的最小操作次数。

分析

再次感谢@前额叶没长好的讲解qaq

我们观察这一组数据

100 -> 101 -> 111 -> 110 -> 010 -> 011 -> 001 -> 000

观察到 100->...->010->...->000是三个位数不同的状态,也就说在操作过程中位数是单调递减的!我们再用多组数据观察发现,要使操作次数最小,他们的操作路径都是固定方向的一条直线!同时上面三个二进制数也是位数发生改变后的首个二进制数 。

不妨设f(xxxxxx)表示将二进制xxxxxx变为0的最小操作次数。

  • 当xxxxxx形如11xxxx时,要使它位数降低,只有题目中的操作二才能做到。我们是不是应该要将后面未知的xxxx变为0000呢,即将11xxxx变为110000,从而满足操作二的执行条件,由此110000通过操作二变为010000。总的来说,就是对11xxxx->…->110000->…->010000->….->000000(只保留了关键步骤),这样的思想就是计算汉诺塔时候用到的思想!故操作次数f(11xxxx)=f(00xxxx)+1+f(010000)(f(00xxxx)表示11xxxx变为110000的操作次数,1表示110000变为010000的操作次数,f(010000)表示从010000变为000000操作次数
  • 当xxxxxx形如10xxxx时,我们就要先将0xxxx转化为10000即将10xxxx变为110000,接下来操作与上面情况相同了。操作次数即为f(10xxxx)=f(10000)-f(xxxx)+1+f(10000),(f(10000)-f(xxxx)表示将10xxxx变为110000的操作次数)
class Solution {
private:
unordered_map<int, int> f;
public:
int DFS(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
if (f.count(n) > 0) return f[n];
int hiBit = 1 << 30, loBit = 1 << 29;
int ans = 0;
while (hiBit > 0) {
if (n & hiBit) {
if (n & loBit) {
ans = DFS(n ^ (hiBit | loBit)) + 1 + DFS(loBit);
break;
}
else {
ans = DFS(loBit) - DFS(n ^ hiBit) + 1 + DFS(loBit);
break;
}
}
else {
hiBit >>= 1;
loBit >>= 1;
}
}
return f[n] = ans;
}
int minimumOneBitOperations(int n) {
f.clear();
return DFS(n);
}
};

另外,题目要求的操作实际上,与格雷码的枚举基本一致,可参考此篇题解

LeetCode周赛#209的更多相关文章

  1. 【Leetcode周赛】从contest-111开始。(一般是10个contest写一篇文章)

    Contest 111 (题号941-944)(2019年1月19日,补充题解,主要是943题) 链接:https://leetcode.com/contest/weekly-contest-111 ...

  2. 2017-3-12 leetcode 167 209 216

    ---恢复内容开始--- 对于每次开机avast喊出的“已经检测到危害”实在忍无可忍了(它只能检测到不能根除很气..)于是重装了系统,回到了win10感觉不赖. =================== ...

  3. 拼写单词[哈希表]----leetcode周赛150_1001

    题目描述: 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我 ...

  4. 【Leetcode周赛】从contest-41开始。(一般是10个contest写一篇文章)

    Contest 41 ()(题号) Contest 42 ()(题号) Contest 43 ()(题号) Contest 44 (2018年12月6日,周四上午)(题号653—656) 链接:htt ...

  5. 【Leetcode周赛】从contest-51开始。(一般是10个contest写一篇文章)

    Contest 51 (2018年11月22日,周四早上)(题号681-684) 链接:https://leetcode.com/contest/leetcode-weekly-contest-51 ...

  6. 【Leetcode周赛】从contest-71开始。(一般是10个contest写一篇文章)

    Contest 71 () Contest 72 () Contest 73 (2019年1月30日模拟) 链接:https://leetcode.com/contest/weekly-contest ...

  7. 【Leetcode周赛】从contest-81开始。(一般是10个contest写一篇文章)

    Contest 81 (2018年11月8日,周四,凌晨) 链接:https://leetcode.com/contest/weekly-contest-81 比赛情况记录:结果:3/4, ranki ...

  8. 【Leetcode周赛】从contest-91开始。(一般是10个contest写一篇文章)

    Contest 91 (2018年10月24日,周三) 链接:https://leetcode.com/contest/weekly-contest-91/ 模拟比赛情况记录:第一题柠檬摊的那题6分钟 ...

  9. 【Leetcode周赛】从contest-121开始。(一般是10个contest写一篇文章)

    Contest 121 (题号981-984)(2019年1月27日) 链接:https://leetcode.com/contest/weekly-contest-121 总结:2019年2月22日 ...

随机推荐

  1. 注意由双大括号匿名类引起的serialVersionUID编译告警

    问题描述 最近版本组织清理编译告警,其中有这么一条比较有意思,之前没见过,拿出来说一说 "serializable class anonymous com.demo.Main$1 has n ...

  2. 一款强大的双色球走势图,助你500W梦想,js+mvc+html

    序言 估计每个人都有中500W的梦想,我关注双色球也有一定年数了,可最多中也只有10块钱,这已经算是最大的奖,最近闲来无事,研究下怎么去开发双色球的走势图,觉得还是蛮有意思的,用MVC+JS+HTMl ...

  3. mysql 事务的日志

    事务的日志 1.redo log redo:"重做",记录的是,内存数据页的变化过程 1)作用 在事务ACID过程中,实现的是 "D" 持久化的作用. 2)工作 ...

  4. 使用painless将ElasticSearch字符串拆分为数组

    一.实现场景: ES字符串类型字段imgs,有些历史数据是用逗号分隔的字符串,需要将历史数据拆分为数组形式. 示例: 1.构造测试数据: 创建索引并推送几条典型的历史数据,涵盖以下几种情况: 逗号分隔 ...

  5. select单表查询和多表查询

    数据表 1).学生表: Student 字段: (SID,Sname,Sage,Ssex) -SID学生编号,Sneme学生姓名,Sage出生年月,Ssex学生性别 2).课程表: Course 字段 ...

  6. PS2018 激活

  7. numpy矩阵

    一.创建矩阵 Numpy提供了ndarray来进行矩阵的操作,在Numpy中 矩阵继承于NumPy中的二维数组对象,但矩阵区别于数组,不可共用数组的运算规律. 1.mat("第0行:第1行: ...

  8. 2020提高组模拟赛7 StormWind

    StormWind 中文 切换语言(Change Language) 时间:4s   空间:512M 题目描述: 风暴城建造的防线错综复杂,可以抽象成一个有$n$个点$m$条边的有向拓扑图,暴风城的最 ...

  9. How to Convert and Import VHD to VMDK (VMWare)

    VHD or Virtual Hard Disk is the disk image format used by Microsoft virtualization software such as ...

  10. 一款基于.NET Core的认证授权解决方案-葫芦藤1.0开源啦

    背景 18年公司准备在技术上进行转型,而公司技术团队是互相独立的,新技术的推动阻力很大.我们需要找到一个切入点.公司的项目很多,而各个系统之间又不互通,导致每套系统都有一套登录体系,给员工和客户都带来 ...