min_jumps_end_prime_tele.c (3782B)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | // 3629. Minimum Jumps to Reach End via Prime Teleportation #include "leetcode.h" /* * you are given an integer array 'nums' of length 'n'. you start at index 0, * and your goal is to reach index 'n - 1'. from any index 'i', you may perform * onee of the following operations: adjacent step: jump to index 'i + 1' or 'i * - 1', if the index is within bounds, or prime teleportation: if 'nums[i]' is * a prime number, you may instantly jump to any index 'j != i' such that * 'nums[j] % p == 0'. return the minimum number of jumps to reach the index 'n * - 1'. */ #define MAX_SIZE 1000001 #define HASH_SIZE 10007 typedef struct { int *data; int size; int cap; } vector; typedef struct node { int key; vector values; struct node *next; } node; static node *hash_table[HASH_SIZE]; static vector factors[MAX_SIZE]; static bool precomputed = false; void vector_push(vector *v, int val) { if (v->size == v->cap) { v->cap = v->cap == 0 ? 2 : v->cap * 2; v->data = (int *)realloc(v->data, v->cap * sizeof(int)); } v->data[v->size++] = val; } void hash_push(int key, int val) { int h = abs(key) % HASH_SIZE; node *cur = hash_table[h]; while (cur) { if (cur->key == key) { vector_push(&cur->values, val); return; } cur = cur->next; } node *new_node = (node *)malloc(sizeof(node)); new_node->key = key; memset(&new_node->values, 0, sizeof(vector)); vector_push(&new_node->values, val); new_node->next = hash_table[h]; hash_table[h] = new_node; } vector *hash_get(int key) { int h = abs(key) % HASH_SIZE; node *cur = hash_table[h]; while (cur) { if (cur->key == key) return &cur->values; cur = cur->next; } return NULL; } void precompute() { if (precomputed) return; for (int i = 2; i < MAX_SIZE; i++) { if (factors[i].size == 0) { for (int j = i; j < MAX_SIZE; j += i) { vector_push(&factors[j], i); } } } precomputed = true; } void clear_hash() { for (int i = 0; i < HASH_SIZE; i++) { node *cur = hash_table[i]; while (cur) { node *tmp = cur; cur = cur->next; free(tmp->values.data); free(tmp); } hash_table[i] = NULL; } } int minJumps(int *nums, int numsSize) { precompute(); clear_hash(); int n = numsSize; for (int i = 0; i < n; i++) for (int p_idx = 0; p_idx < factors[nums[i]].size; p_idx++) hash_push(factors[nums[i]].data[p_idx], i); bool *vis = (bool *)calloc(n, sizeof(bool)); int *q = (int *)malloc(n * sizeof(int)); int q_start = 0, q_end = 0; vis[0] = true; q[q_end++] = 0; int ans = 0; while (q_start < q_end) { int level_size = q_end - q_start; for (int k = 0; k < level_size; k++) { int i = q[q_start++]; if (i == n - 1) { free(vis); free(q); return ans; } if (i > 0 && !vis[i - 1]) { vis[i - 1] = true; q[q_end++] = i - 1; } if (i < n - 1 && !vis[i + 1]) { vis[i + 1] = true; q[q_end++] = i + 1; } if (factors[nums[i]].size == 1) { int p = nums[i]; vector *v = hash_get(p); if (v) { for (int j_idx = 0; j_idx < v->size; j_idx++) { int j = v->data[j_idx]; if (!vis[j]) { vis[j] = true; q[q_end++] = j; } } v->size = 0; } } } ans++; } return -1; } int main() { int n1[] = {1, 2, 4, 6}; int n2[] = {2, 3, 4, 7, 9}; int n3[] = {4, 6, 5, 8}; int r1 = minJumps(n1, ARRAY_SIZE(n1)); int r2 = minJumps(n2, ARRAY_SIZE(n2)); int r3 = minJumps(n3, ARRAY_SIZE(n3)); printf("%d\n", r1); assert(r1 == 2); printf("%d\n", r2); assert(r2 == 2); printf("%d\n", r3); assert(r3 == 3); } |