LeetCode Day 5:图

图在C语言中的表示

邻接表表示

#include "uthash.h"
// 利用哈希表存每个节点的相邻节点
typedef struct {
    int key;
    UT_hash_handle hh;
} HashItem;

// 定义二维哈希表
/*
	graph[num]表示节点num的所有相邻节点的列表
*/
HashItem **graph = (HashItem **)malloc(sizeof(HashItem *) * (n + 1));

// 插入相邻节点(在节点prev的邻接表插入)
pEntry = (HashItem *)malloc(sizeof(HashItem));
pEntry->key = next;
HASH_ADD_INT(graph[prev], key, pEntry);

// 查询prev的邻接表中是否有节点next
HashItem *pEntry = NULL;
HASH_FIND_INT(graph[prev], &next, pEntry);

// 遍历节点num的邻接表
for (HashItem *pEntry = graph[num]; pEntry != NULL; pEntry = pEntry->hh.next) {
    int next = pEntry->key;
    indegrees[next]--;
    if (indegrees[next] == 0) {
        queue[tail++] = next;
    }
}

拓扑排序

问题描述(剑指 Offer II 115. 重建序列)

给定一个长度为 n 的整数数组 nums ,其中 nums 是范围为 [1,n] 的整数的排列。还提供了一个 2D 整数数组 sequences ,其中 sequences[i] 是 nums 的子序列。检查 nums 是否是唯一的最短 超序列 。最短 超序列 是 长度最短 的序列,并且所有序列 sequences[i] 都是它的子序列。对于给定的数组 sequences ,可能存在多个有效的 超序列 。
例如,对于 sequences = [[1,2],[1,3]] ,有两个最短的 超序列 ,[1,2,3] 和 [1,3,2] 。
而对于 sequences = [[1,2],[1,3],[1,2,3]] ,唯一可能的最短 超序列 是 [1,2,3] 。[1,2,3,4] 是可能的超序列,但不是最短的。
如果 nums 是序列的唯一最短 超序列 ,则返回 true ,否则返回 false 。子序列 是一个可以通过从另一个序列中删除一些元素或不删除任何元素,而不改变其余元素的顺序的序列。

思路关键词:拓扑排序

代码实现:

// #include "uthash.h"
// 定义结构体
typedef struct {
    int key;
    UT_hash_handle hh;
} HashItem;

bool sequenceReconstruction(int* nums, int numsSize, int** sequences, int sequencesSize, int* sequencesColSize){
    int n = numsSize;
    int *indegrees = (int *)malloc(sizeof(int) * (n + 1));
    // 定义Hash表指针
    HashItem **graph = (HashItem **)malloc(sizeof(HashItem *) * (n + 1));
    memset(indegrees, 0, sizeof(int) * (n + 1));
    for (int i = 0; i <= n; i++) {
        graph[i] = NULL;
    }
    for (int j = 0; j < sequencesSize; j++) {
        for (int i = 1; i < sequencesColSize[j]; i++) {
            int prev = sequences[j][i - 1], next = sequences[j][i];
            HashItem *pEntry = NULL;
            // 查询
            HASH_FIND_INT(graph[prev], &next, pEntry);
            if (NULL == pEntry) {
                pEntry = (HashItem *)malloc(sizeof(HashItem));
                pEntry->key = next;
                // 插入
                HASH_ADD_INT(graph[prev], key, pEntry);
                indegrees[next]++;
            }
        }
    }
    int *queue = (int *)malloc(sizeof(int) * n);
    int head = 0, tail = 0;
    for (int i = 1; i <= n; i++) {
        if (indegrees[i] == 0) {
            queue[tail++] = i;
        }
    }
    while (head != tail) {
        if ((tail - head) > 1) {
            free(queue);
            return false;
        }
        int num = queue[head++];
        // 迭代
        for (HashItem *pEntry = graph[num]; pEntry != NULL; pEntry = pEntry->hh.next) {
            int next = pEntry->key;
            indegrees[next]--;
            if (indegrees[next] == 0) {
                queue[tail++] = next;
            }
        }
    }
    free(queue);
    return true;
}

// 作者:LeetCode-Solution
// 链接:https://leetcode.cn/problems/ur2n8P/solution/zhong-jian-xu-lie-by-leetcode-solution-urxc/
// 来源:力扣(LeetCode)
// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

克隆图

问题描述

给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。
图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。

思路关键词:DFS

代码:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     int numNeighbors;
 *     struct Node** neighbors;
 * };
 */

struct Node *cloneDFS(struct Node* s, struct Node** nodes) {
    // s为当前遍历的节点
    struct Node* cloneNode = (struct Node*) malloc(sizeof(struct Node));
    nodes[s->val] = cloneNode;
    cloneNode->val = s->val;
    cloneNode->numNeighbors = s->numNeighbors;
    struct Node** newNeighbors = (struct Node**) malloc((cloneNode->numNeighbors) * sizeof(struct Node*));
    cloneNode->neighbors = newNeighbors;
    int i;
    for (i = 0;i < cloneNode->numNeighbors;i++) {
        if (!nodes[s->neighbors[i]->val]) {
            struct Node* n = cloneDFS(s->neighbors[i], nodes);
            cloneNode->neighbors[i] = n;
            nodes[s->neighbors[i]->val] = n;
        } else {
            cloneNode->neighbors[i] = nodes[s->neighbors[i]->val];
        }
    }
    return cloneNode;
}

struct Node *cloneGraph(struct Node *s) {
    if (!s) return NULL;
    struct Node** nodes = (struct Node**) malloc(101 * sizeof(struct Node*));
    int i;
    for (i = 0;i < 101;i++) {
        nodes[i] = NULL;
    }
	return cloneDFS(s, nodes);
}

DFS+记忆化搜索

问题描述:329. 矩阵中的最长递增路径

给定一个 m x n 整数矩阵 matrix ,找出其中 最长递增路径 的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你 不能 在 对角线 方向上移动或移动到 边界外(即不允许环绕)。

int d[5] = {0, 1, 0, -1, 0};
int R;
int C;

int dfs(int** matrix, int r, int c, int** memory) {
    if (memory[r][c] > 0) return memory[r][c];
    int i;
    int cans = 1;
    for (i = 0;i < 4;i++) {
        int nr = r + d[i];
        int nc = c + d[i+1];
        if (nr >= 0 && nr < R && nc >= 0 && nc < C) {
            if (matrix[nr][nc] > matrix[r][c]) {
                int ans = dfs(matrix, nr, nc, memory) + 1;
                if (ans > cans) {
                    cans = ans;
                }
            }
        } else {
            continue;
        }
    }
    // 记录以该点为起点的最长递增路径
    memory[r][c] = cans;
    return cans;
}

int longestIncreasingPath(int** matrix, int matrixSize, int* matrixColSize){
    R = matrixSize;
    C = matrixColSize[0];
    int i, j;
    // 初始化记忆搜索数组
    int** memory = (int**) malloc(R * sizeof(int*));
    for (i = 0;i < R;i++) {
        memory[i] = (int*) malloc(C * sizeof(int));
        memset(memory[i], 0, C * sizeof(int));
    }
    int cans = 1;
    for (i = 0;i < R;i++) {
        for (j = 0;j < C;j++) {
            int ans = dfs(matrix, i, j, memory);
            if (ans >= cans) {
                cans = ans;
            }
        }
    }
    return cans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值