ARTS-第-26-期_主线程

阅读本文大概需要 8 分钟。

每周完成一个 ARTS

Algorithm LeetCode 56. Merge Intervals。

Review 分享一篇有关多线程的介绍。 
Tip 分享在 Qt 里面重定向 QDebug 输出到文件,并附上日期。 
Share 关于健康和睡眠的思考。

PS:由于公众号不支持添加外链,所以大家遇到有链接的地方滑到文章最下面点击阅读原文就可以访问了哈,如果觉得文章不错,欢迎分享给周围的朋友们哈

ARTS-第-26-期_主线程_02

1.Algorithm

LeetCode 56. Merge Intervals 难度:[Medium]

【题意】区间合并问题

Example 1:

Input: [[1,3],[2,6],[8,10],[15,18]]

Output: [[1,6],[8,10],[15,18]]

Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].

Example 2:

Input: [[1,4],[4,5]]

Output: [[1,5]]

Explanation: Intervals [1,4] and [4,5] are considered overlapping.

【思路】

贪心思路,将初始区间序列 ins 按照左端点的从小到大排序,接着遍历 ins。 一开始将第一个区间 ins[0] 放入结果区间序列 res,接着每次遍历到一个新的区间 [l,r],将其与当前合并后的最后一个区间 [L,R] 比较:

【1】若 l <= R,说明新区间与当前最有一个区间有重叠,应该将这两个区间合并,也就需要修改当前最后一个区间为 [L,max(r,R)]。

【2】若 l > R,说明新区间与当前最后一个区间没有重叠,所以不需要合并,直接将新区间加入结果序列res,成为新的最后一个区间。

算法正确性:

在上述贪心思路中,只考虑了新区间的左端点与最后一个区间的右端点的大小比较,最后只会对最后区间的右端点进行修改,却不会修改左端点。之所以不考虑左端点,是因为初始化时已经将 ins 按照左端点排序,保证后遍历的左端点 l >= 之前遍历过的左端点 L。 算法复杂度为 O(nlogn)。

【解法一】(C++)

/*
Author: https://github.com/rongweihe
Time: 2019-04-14
*/
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
static bool cmp(const Interval &a, const Interval &b) {
return a.start < b.start;
}
vector<Interval> merge(vector<Interval>& intervals) {
vector <Interval> res;
if (intervals.empty()) return res;
sort(intervals.begin(), intervals.end(), cmp);
res.push_back(intervals[0]);
int cnt = intervals.size();
for (int i = 1; i < cnt; i++) {
if (intervals[i].start <= res.back().end) {
res.back().end = max(res.back().end, intervals[i].end);
}
else {
res.push_back(intervals[i]);
}
}
return res;
}
};

2.Review

本周阅读了一篇 medium 的文章: 

A gentle introduction to multithreading  www.internalpointers.com 

介绍多线程的一些知识。

1、主线程和子线程

在操作系统中运行进程不是同时执行多个操作的唯一方法。每个进程都能够在其自身内运行同步子任务,称为线程。可以将线程视为流程本身的一部分。每个进程在启动时至少触发一个线程,称为主线程。然后,根据程序/程序员的需要,可以启动或终止其他线程。 多线程是关于在单个进程中运行多个线程。

例如,媒体播放器可能会运行多个线程:一个用于呈现界面;通常是主线程-,另一个用于播放音乐,等等。

2、进程间通信(IPC)

每个进程都有自己的操作系统分配的内存块。默认情况下,内存无法与其他进程共享:浏览器无法访问分配给媒体播放器的内存,反之亦然。如果运行相同进程的两个实例,即如果启动浏览器两次,则会发生同样的情况。操作系统将每个实例视为一个新进程,并分配了自己独立的内存部分。因此,默认情况下,两个或多个进程无法共享数据,除非它们执行高级技巧 - 即所谓的进程间通信(IPC)。

与进程不同,线程共享由操作系统分配给其父进程的相同内存块:媒体播放器主界面中的数据可以由音频引擎轻松访问,反之亦然。因此,两个线程更容易相互通信。最重要的是,线程通常比进程更轻:它们占用的资源更少,创建速度更快,这就是为什么它们也被称为轻量级进程。

3、何时使用多线程?

为什么进程应该使用多个线程?正如之前提到的,并行处理可以大大加快速度。假设要在电影编辑器中渲染电影。编辑器可以足够聪明,可以跨多个线程传播渲染操作,每个线程处理最终影片的一大块。因此,如果使用一个线程,任务将花费一个小时,两个线程需要 30 分钟;用四个线程 15 分钟,依此类推。使用多线程真的那么简单吗?有三个要点需要考虑:

【1】并非每个程序都需要多线程。如果您的应用程序执行顺序操作或经常等待用户执行某些操作,多线程可能不是那么有用;

【2】只是不向应用程序抛出更多线程以使其运行更快:必须仔细考虑和设计每个子任务以执行并行操作;

【3】并非 100% 保证线程将真正并行执行其操作,它实际上取决于底层硬件。

最后一个是至关重要的:如果计算机不同时支持多个操作,操作系统必须伪造它们。并发视为具有同时运行的任务的感知,而真正的并行作为同时运行的任务。

这篇文章另外还介绍了其它的精彩的内容,有兴趣的可以阅读原文。

3. Tip

分享在 Qt 里面重定向 QDebug 输出到文件,并附上日期

介绍

代码比较简单,就是一个函数,在 main 中调用即可

函数申明

void setDebugOutput(const QString &targetFilePath, const bool &argDateFlag = false);

函数使用

不动态追加日期

setDebugOutput( "/root/log/all.log" );

动态追加日期

setDebugOutput( "/root/log/%1.log", true );

函数实现 代码有点长,这里就不贴出了,点击阅读原文即可查看

4. Share

关于最近看到一些因为不良习惯导致猝死的新闻。比如某研究生通宵三天写作业导致猝死,令人唏嘘的同时又值得我们深刻反思健康这个话题。

我一直认为,健康是第一位的,如果把人生比作一串数字的话,健康是 1,事业,财富,婚姻,名利等等都是后面的 0,由 1 和 0可以组成 10, 100 等 N 种不同大小的值,如果没有健康这个 1,其他条件再多也只是 0。

有个误区在于:有人可能会觉得为了身体,要去多多运动和健身,哪怕再忙再累,都得去跑步健身去,我觉得前提是,得要保证足够的睡眠,基本的睡眠都得不到保障,就别去做高强度运动了。

总结一下就是:

1、成年人每天最起码要保证 7-8 小时睡眠,睡眠是最根本的。

2、偶尔忙,睡眠偶尔不够可以理解,但是长期没有足够的睡眠保证,身体一定出问题。

3、我觉得拼搏和身体不冲突,重要的了解自己的身体状况,有异样及时就医,在基本睡眠保证的情况下,有时间精力去健身运动都是可以的。

你有什么别的思考和见解呢?欢迎留言一起交流~

PS:以上个人看法,仅供参考。


ARTS-第-26-期_区间合并_03