图在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;
}