LeetCode解题方法10-广度优先遍历(队列)+二分法优化

1.题目

  1. 杀死进程
  2. 跳跃游戏 IV

2.思路

这两道题都比较适合用广度优先算法,
广度优先算法的思路是先把第一步的所有节点保存在队列中,然后依次取出队列中的节点,再将第二步的节点进行保存,直到达到条件或全部搜索完毕停止。

3.题目582

题目
给 n 个进程,每个进程都有一个独一无二的 PID (进程编号)和它的 PPID (父进程编号)。

每一个进程只有一个父进程,但是每个进程可能会有一个或者多个孩子进程。它们形成的关系就像一个树状结构。只有一个进程的 PPID 是 0 ,意味着这个进程没有父进程。所有的 PID 都会是唯一的正整数。

我们用两个序列来表示这些进程,第一个序列包含所有进程的 PID ,第二个序列包含所有进程对应的 PPID。

现在给定这两个序列和一个 PID 表示你要杀死的进程,函数返回一个 PID 序列,表示因为杀这个进程而导致的所有被杀掉的进程的编号。

当一个进程被杀掉的时候,它所有的孩子进程和后代进程都要被杀掉。

你可以以任意顺序排列返回的 PID 序列。

示例 1:

输入:
pid = [1, 3, 10, 5]
ppid = [3, 0, 5, 3]
kill = 5
输出: [5,10]
解释:
3
/
1 5
/
10
杀掉进程 5 ,同时它的后代进程 10 也被杀掉。

示例 2:
输入:
pid = [1, 3, 10, 5, 6 ,7]
ppid = [5, 0, 5, 3, 10, 1]
kill = 5
输出: [5,10]
注意:

被杀掉的进程编号一定在 PID 序列中。
n >= 1.

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/kill-process
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例2步骤:
1.可以用广度优先遍历,先将父节点5放入队列1,输出5。
2.取出5,搜索所有父节点为5的节点,并将子节点1,10放入队列2,输出1,10;
3.之前的队列1为空,开始取队列2的值
4.取出1,搜索所有父节点为1的节点,并将子节点7放入队列2,输出7;
5.取出10,搜索所有父节点为10的节点,并将子节点6放入队列2,输出6;
6.之前的队列2为空,开始取队列3的值
7.取出7,搜索所有父节点为7的节点,没有找到,不向队列加入元素;
8.取出6,搜索所有父节点为6的节点,没有找到,不向队列加入元素;
9.队列为空,停止遍历

此外,搜索时为了避免超时,用了二分法搜索。

代码:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
typedef struct {
    int sonPid;
    int fatherPid;
} Node;
bool CalMinAndMaxPos(Node* rec, int len, int* min, int* max, int target)
{
    int i, j, mid, val;
    bool ret = false;
    i = 0;
    j = len - 1;
    while (i <= j) {
        mid = (i + j) / 2;
        val = rec[mid].fatherPid;
        if (val == target) {
            *min = mid;
            j = mid - 1;
            ret = true;
        } else if (val > target) {
            j = mid - 1;
        } else {
            i = mid + 1;
        }
    }
    i = 0;
    j = len - 1;
    while (i <= j) {
        mid = (i + j) / 2;
        val = rec[mid].fatherPid;
        if (val == target) {
            *max = mid;
            i = mid + 1;
        } else if (val > target) {
            j = mid - 1;
        } else {
            i = mid + 1;
        }
    }
    return ret;
}
void Bfs(Node* rec, int pidSize, int* killList, int* returnSize, int kill)
{
    int* queue;
    int* newQueue;
    int* temp;
    int i, j, max, min;
    queue = (int*)malloc(sizeof(int) * pidSize);
    newQueue = (int*)malloc(sizeof(int) * pidSize);
    int queLen, newQueLen;
    killList[*returnSize] = kill;
    (*returnSize)++;
    queue[0] = kill;
    queLen = 1;
    while (queLen) {
        newQueLen = 0;
        for (i = 0; i < queLen; i++) {
            if (CalMinAndMaxPos(rec, pidSize, &min, &max, queue[i]) == false) {
                continue;
            }
            for (j = min; j <= max; j++) {
                    killList[*returnSize] = rec[j].sonPid;
                    (*returnSize)++;
                    newQueue[newQueLen++] = rec[j].sonPid;
            }
        }
        queLen = newQueLen;
        temp = queue;
        queue = newQueue;
        newQueue = temp;
    }
    
}
int Cmp(const void *a1, const void *a2)
{
    return ((Node*)a1)->fatherPid - ((Node*)a2)->fatherPid;
}

int* killProcess(int* pid, int pidSize, int* ppid, int ppidSize, int kill, int* returnSize){
    /*广度优先搜索*/
    int* killList;
    Node* rec;
    int i;
    killList = (int*)malloc(sizeof(int) * pidSize);
    (*returnSize) = 0;
    if (pidSize < 1) {
        return killList;
    }
    
    rec = (Node*)malloc(sizeof(Node) * pidSize);
    
    for (i = 0; i < pidSize; i++) {
        rec[i].sonPid = pid[i];
        rec[i].fatherPid = ppid[i];
    }
    qsort(rec, pidSize, sizeof(Node), Cmp);
    Bfs(rec, pidSize, killList, returnSize, kill);
    return killList;
}

你可能感兴趣的:(LeetCode解题方法10-广度优先遍历(队列)+二分法优化)