孤儿进程
父进程先于子进程结束,也就意味着,此时子进程变成了一个孤儿进程,在Linux系统中,所有孤儿进程都自动变成init进程的子进程。
也就是说,某一子进程的父进程结束后,该子进程调用getppid()将会返回1。
但是在图形界面下的一个后台守护进程,会成为孤儿进程的父进程。
长度最小的子数组
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0, right = 0, n = nums.size();
int ret = INT_MAX;
int sum = nums[left];
while(left <= right && right < n){
if(sum >= target){
ret = min(ret, right-left+1);
sum -= nums[left];
left++;
}else{
right++;
if(right < n){
sum += nums[right];
}
}
}
return ret == INT_MAX ? 0: ret;
}
};
路径总和
/**
* 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 dfs(TreeNode* root, int targetSum, int sum){
if(root == nullptr){
return false;
}
if(root->left == nullptr && root->right == nullptr){
sum += root->val;
return sum == targetSum;
}
return dfs(root->left, targetSum, sum+root->val) || dfs(root->right, targetSum, sum+root->val);
}
bool hasPathSum(TreeNode* root, int targetSum) {
return dfs(root, targetSum, 0);
}
};
完全二叉树的节点个数
给一棵完全二叉树的根节点root,求出该树的节点个数。
对于任意二叉树,都可以通过深度优先搜索或广度优先搜索计算节点的个数,时间复杂度和空间复杂度都是O(N)。
根节点位于第0层,最大层数为h。
守护进程
守护进程(daemon),是运行在后台的一种特殊进程,它独立于控制终端,并且周期性地执行某种任务或等待处理某些事情的发生,主要表现为两个特点:
- 长期运行。守护进程是一种生存期很长的一种进程,它们一般在系统启动时开始运行,除非强行终止,否则直到系统关机之前都会保持运行。与守护进程相比,普通进程都是在用户登录或执行程序时创建,在运行结束或用户注销时终止,但守护进程不受用户登录注销的影响,它们将会一只运行着,直到系统关机。
- 与控制终端脱离。普通进程都是和控制终端想绑定的,会受到终端的控制、影响;但守护进程它脱离了控制终端,目的就是为了不受到控制终端的控制、影响,同时守护进程也不会将运行过程的信息通过终端显示出来,更不会通过终端与用户进行交互。
Linux系统中有很多种系统服务,大多数服务都是通过守护进程实现的,譬如系统日志服务syslog,web服务httpd,邮件服务sendmail和数据库服务mysqld等。守护进程名字通常以d结尾。
如何编写守护进程
守护进程的重点在于脱离控制终端。
-
创建子进程,终止父进程。
-
子进程调用setsid创建新的会话。
-
将当前工作目录更改为根目录。
-
重新设置文件权限掩码umask。
-
关闭打开的文件描述符
-
忽略SIGCHLD信号。
将有序数组转换为二叉搜索树
/**
* 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:
TreeNode* helper(vector<int>& nums, int left, int right) {
if (left == right) {
return new TreeNode(nums[left]);
}
if (left < right) {
int mid = (left + right) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = helper(nums, left, mid - 1);
root->right = helper(nums, mid + 1, right);
return root;
}
return nullptr;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
int n = nums.size();
if (n == 1) {
return new TreeNode(nums[0]);
}
int mid = n / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = helper(nums, 0, mid - 1);
root->right = helper(nums, mid + 1, n - 1);
return root;
}
};
搜索插入位置
假如是在排序数组中寻找一个目标值,那么直接利用二分法就可以在O(log n)找到目标值,但是这题添加了额外条件,如果不存在数组中的时候,需要返回插入顺序。
插入位置。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
//找到第一个大于等于target的元素,其下标就是返回值
//如果一直找不到,意味着所有元素都小于target,直接放到末尾。
int left = 0, right = nums.size()-1, ret = nums.size();
while(left <= right){
int mid = left + ((right-left) >> 1);
if(nums[mid] >= target){
ret = mid;
right = mid - 1;
}else{
left = mid + 1;
}
}
return ret;
}
};
搜索二维矩阵
矩阵满足:
- 每行从左到右非严格递增
- 没好第一个整数大于前一行最后一个整数。
给一个整数target,如果target在矩阵中,返回true,否则返回false。
两次二分查找
由于每行的第一个元素大于前一行的最后一个元素,所以每行第一个元素一定大于前一行顶一个元素,所以第一列是升序的。
可以对矩阵的第一列的元素二分查找,找到最后一个小于等于target目标值的元素,然后在该元素所在行中二分查找目标值。
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size(), n = matrix[0].size();
int i = 0, j = 0;
int index = -1;
for(i=0; i<m; i++){
if(matrix[i][0] <= target){
index = i;
}
}
if(index == -1){
return false;
}
for(j=0; j<n; j++){
if(matrix[index][j] == target){
return true;
}
}
return false;
}
};
跳跃游戏二
贪心地进行正向查找,每次找到可到达的最远的位置,就可以在线性时间内得到最少跳跃次数。
维护能够到达的最大下标位置,记为边界。到达边界时,更新边界,并把跳跃次数加1。
class Solution {
public:
int jump(vector<int>& nums) {
int maxPos = 0, end = 0, n = nums.size(), step = 0;
for (int i = 0; i < n - 1; i++) {
if (maxPos >= i) { //i处可达
maxPos = max(maxPos, i + nums[i]);
if (i == end) {
end = maxPos;
step++;
}
}
}
return step;
}
};
完全二叉树的节点个数
/**
* 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 checkNode(TreeNode* root, int level, int index){
for(int i=level-2; i>=0 && root!=nullptr; i--){
if((index >> i) & 1){
root = root->right;
}else{
root = root->left;
}
}
return root != nullptr;
}
int countNodes(TreeNode* root) {
int level = 0;
TreeNode* p = root;
while(p){
level++;
p = p->left;
}
if(level == 0 || level == 1){
return level;
}
int left = 1 << (level - 1);
int right = (1 << level) - 1;
int ret = 0;
while(left <= right){
int mid = left + ((right - left) >> 1);
if(checkNode(root, level, mid)){
ret = mid;
left = mid + 1;
}else{
right = mid - 1;
}
}
return ret;
}
};