Algorithm
https://leetcode-cn.com/problems/happy-number/
编写一个算法来判断一个数是不是“快乐数”。
一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。
示例:
输入: 19
输出: true
解释:
1
2
+
9
2
=
82
1^2 + 9^2 = 82
12+92=82
8
2
+
2
2
=
68
8^2 + 2^2 = 68
82+22=68
6
2
+
8
2
=
100
6^2 + 8^2 = 100
62+82=100
1
2
+
0
2
+
0
2
=
1
1^2 + 0^2 + 0^2 = 1
12+02+02=1
思路1:
这道题定义了一种快乐数,就是说对于某一个正整数,如果对其各个位上的数字分别平方,然后再加起来得到一个新的数字,再进行同样的操作,如果最终结果变成了1,则说明是快乐数,如果一直循环但不是1的话,就不是快乐数,那么现在任意给我们一个正整数,让我们判断这个数是不是快乐数,题目中给的例子19是快乐数,那么我们来看一个不是快乐数的情况,比如数字11有如下的计算过程:
1^2 + 1^2 = 2
2^2 = 4
4^2 = 16
1^2 + 6^2 = 37
3^2 + 7^2 = 58
5^2 + 8^2 = 89
8^2 + 9^2 = 145
1^2 + 4^2 + 5^2 = 42
4^2 + 2^2 = 20
2^2 + 0^2 = 4
我们发现在算到最后时数字4又出现了,那么之后的数字又都会重复之前的顺序,这个循环中不包含1,那么数字11不是一个快乐数,发现了规律后就要考虑怎么用代码来实现,我们可以用 HashSet 来记录所有出现过的数字,然后每出现一个新数字,在 HashSet 中查找看是否存在,若不存在则加入表中,若存在则跳出循环,并且判断此数是否为1,若为1返回true,不为1返回false,代码如下:
class Solution {
public:
bool isHappy(int n) {
unordered_set<int> st;
while (n != 1) {
int sum = 0;
while (n) {
sum += (n % 10) * (n % 10);
n /= 10;
}
n = sum;
if (st.count(n)) break;
st.insert(n);
}
return n == 1;
}
};
思路二:
这个单链表快慢指针讲很多了,可以直接跳过,去看看算法规模分析吧!
泛化链表结构:如果我们 把链表的节点看成问题中的状态 的话,它可以代表问题中的一个数字、一个阶段等等,是很泛化的东西。而链表的唯一指向关系它又代表什么呢?它其实代表着 状态与状态之间是唯一确定转换 的。也就是说从当前状态是唯一确定转换到下一个状态的。显然快乐数的转换规则完美的符合了这个特性。
我们根据题目的意思就将 1 作为链表的结尾即 NULL。
那么在单链表中一直走不到空地址意味着什么?就意味着链表有环呗。那么这个快乐数问题就被抽象为链表中是否有环的问题。即,如果这个链表有环那么就不是快乐数,如果链表没环,能指到空地址 1 的话那就说明这个数就是快乐数。
从上面我们得到了解决这个问题的算法思维,但是会不会出现这个链表太长了,有上个几千、几万、几十万的链表单元,影响我们找不到结果呢?我们来考虑一下这个算法的规模。
首先,如果输入值为 int,那么能知道 int 最多也就是一个以 2 开头的 10 位的数字。接着我们来考虑这样一个问题,在 int 数据范围中,哪一个数字 n 它所对应的下一个数字 n 是最大的?
我们能构造得到 1 999 999 999,那么只有构造出 1 个 1 ,9 个 9 的数字在 int 范围内就是最大的,那么下一个节点时多少呢?根据快乐数的定义能得到 9^2 \times9 + 1 = 7309
2
×9+1=730,那么 730 就是在整形范围之内任何一个数字所能映射到的下一个数字都不会超过 730,也就意味着当前所抽象出来的链表结构中节点数目最多不会超过 730 个,如果快指针一次走两步、慢指针一次走一步的话,那么慢指针走的最多,也只不过走了 731\times2 = 1462731×2=1462 步,而快指针就是走了 731731 步。
所以至此就证明完了,在整形快乐数中进行单链表判环的操作的话,操作步骤是有限的,就取个整吧,最多最多也就 2000 步了。所以这个方案是高效可行的。
使用“快慢指针”思想找出循环:“快指针”每次走两步,“慢指针”每次走一步,当二者相等时,即为一个循环周期。此时,判断是不是因为1引起的循环,是的话就是快乐数,否则不是快乐数。
注意:此题不建议用集合记录每次的计算结果来判断是否进入循环,因为这个集合可能大到无法存储;另外,也不建议使用递归,同理,如果递归层次较深,会直接导致调用栈崩溃。不要因为这个题目给出的整数是int型而投机取巧。
就像跑步一样,快乐数跑的是100m冲刺,非快乐数则是在1个400米的环形跑道里无休止的跑下去。
快慢指针就像是专业运动员和业务运动员,在100m的跑道上,两个都会跑到1. 而在环形跑道上,两个指针虽然见面了,但是估计慢指针才跑完一圈,快指针已经跑完两圈了
class Solution {
public:
bool isHappy(int n) {
int slow = n, fast = n;
while(true){
slow = findNext(slow);
fast = findNext(fast);
fast = findNext(fast);
if(slow == fast)
break;
}
return slow == 1;
}
int findNext(int n){
int res = 0;
while(n>0){
res += (n%10) * (n%10);
n /= 10;
}
return res;
}
};
Review
5 Things Confident People Don’t Do
- Asking for reassurance. 总是在反复求得确认
- Ruminating on past mistakes. 总是对过去的错误耿耿于怀
- Expecting too much of themselves. 总是对别人期望过高
- Worrying about things they can’t control. 总是担心不能掌控的事情
- Making decisions based on how they feel.总是按照自己的感觉去决定
5 Habits That Will Help Your Brain Stay in Peak Condition
-
Juggling improves the brain’s grey matter
多做一些有益于大脑的游戏 -
Never go to bed without learning one new thing, your brain will notice: stretch your brain muscles
多锻炼你的大脑肌肉,每天都要学习心得东西 -
Sleeping poorly is linked to rapid reductions in brain volume
睡太少,睡眠不足会影响你的大脑健康 -
Any form of exercise rewires the brain: keep your body active
任何形式地锻炼都能让你的大脑变得活跃 -
Mindfulness is becoming a global phenomenon for a good reason
多冥想,有好处
Tips
对于毕业课题进行总结:
基于视觉无人机的高速公路违章识别系统,背景是为了有效解决高速公路固定人工监控存在的问题,使用无人机在10-12m左右高空巡逻,以斜向下60°的角度拍摄路面情况。通过深度学习目标检测,目标跟踪,图像处理,机器学习以及数学建模的方式实现车辆违章轧实线以及车辆违章越实线的识别。
首先数据是通过无人机拍摄获取的视频通过opencv切分成图片帧。15000张图片作为训练集送入darknet53框架中进行训练,由于源码是C语言的,写了一个python的接口,把目标检测的Bbox给输出出来,这是车辆目标检测模块;车道线检测模块中通过灰度化,OSTU阈值分割,Hough变换得到的二值图上,由于高度原因,车道线具有双边缘的原因,Hough变换之后的线会有很多条,我们希望把多条线按照同属于一条车道线的规律合成唯一的一条车道线。阅读了很多论文,作者们的思路是聚类,因为原图像空间中的线在k,b空间中就是很多点,那么使用FCM均值聚类算法,就能够把按照距离度量接近的点都聚为一类,反映在原图像中就是唯一的车道线。这里有两个明显的缺点,1.是聚类算法的通病,就是初值比较敏感,因为车道线的数量是随着场景变化的,如果换了一个路面,比如长安街,那么可能车道线的数量有10几条,所以这里使用聚类算法不鲁棒;2.在实验有7条车道线的情况下对一张图片做聚类,时间效率非常低,耗时将近1min,这对于最终部署在嵌入式开发板TX2,并挂载到无人机上的目标的达成是不可能的,因为实时性很重要。所以这里摒弃掉了聚类算法,使用自创的相邻角度平均算法,原图中Hough变换生成的每一条车道线的k都能够通过反正切函数arctan()得到一个角度θ,因为无人机的拍摄视角是斜向下60°角度拍摄,因为希望后期能够抓拍到违章车辆的车牌号,在这个场景下,图片中的车道线簇有这样一个规律,同属于一条车道线的车道线簇之间的角度比较接近,不属于同一条车道线的两条车道线之间的角度差距比较大,根据这个规律,从最左边的车道线开始往后遍历,通过设定一个阈值t来判断车道线角度之间的差距是否大于这个t,大于就不同属一条,小于就属于一条车道线。如此,把同属于一条车道线的车道线簇的角度进行平均,得到唯一的一个角度,进而得到斜率和截距,就能够在原图中画出唯一的车道线,这种方法不需要初始化车道线的条数,也能够大大减少运行的时间,只是通过一个简单的规律去遍历得到唯一的车道线。
之后我们通过目标检测模块得到的车辆框,结合刚刚检测出来的车道线,进行数学模型的构建,通过bbox的对角线与车道线相交的四个点连成的向量,利用旋转方向角这个概念,判断是否相交。之前的叙述的过程已经发表了一篇国际会议论文。
车辆违章越线的研究:在已经能够判断车辆是否压线的基础上,触发车辆跟踪的算法deepsort,主要的点在sort以及深度特征提取器,距离度量对比等。不过要有YOLOv3目标检测作为基础,检测框与sort中的kalman滤波器预测的跟踪框之间是需要进行匈牙利匹配的,如何匹配呢?1.一帧内的检测框与对应跟踪框之间IOU大小的马氏距离,但是这种情况下如果遇到车辆速度快,又或者是有其他车辆遮挡的情况下,这种距离就不合适,容易产生ID跳变。所以2.通过一个深度特征提取器,把检测框中的特征提取出来,并与后续多帧的的跟踪框进行余弦距离度量,这两种匹配方式结合起来,才能很好地解决遮挡,ID switch问题,也更稳定。再与轧线之前的车辆检测框的特征进行匹配,由车道线的位置,时序上的同一辆车的位置,结合起来判断车辆是否违章越线。
Share
亲密关系中,既给我们带来了一些限制,又让我们有所拓展,从“我”变成“我们”,我们有依恋的本能,从而变成爱,当这股力量足够强大的时候,就能促使两人走在一起。但是我们又怕,怕这段亲密关系分离,怕林林总总,怕对方伤害自己,怕,让人把爱变成了模仿。
而好的爱情,只会发生在两个独立自主的自由人当中,太粘人,有时候并不好。而物化的爱太过于强烈,我们往往走不出自己。而想要走出自己,走向“我们”,就需要把伤害自己的权利交给别人,其实也意味着把保护自己的权利给了别人。所以,亲密关系的冒险,是一场成长之旅。