From fbb19304cec6033ce80cb5f36a54d724eacc05fc Mon Sep 17 00:00:00 2001 From: snigenigmatic Date: Tue, 22 Apr 2025 16:56:30 +0530 Subject: [PATCH 1/2] feat:added implementation in C --- .../active-traders/active-traders.c | 152 +++++++++++++ .../balanced-system-files-partition.c | 117 ++++++++++ .../longest-subarray/longest-subarray.c | 115 ++++++++++ .../maximum-cost-of-laptop-count.c | 107 +++++++++ .../nearly-similar-rectangles.c | 158 +++++++++++++ .../parallel-processing/parallel-processing.c | 115 ++++++++++ .../password-decryption/password-decryption.c | 99 ++++++++ .../road-repair/road-repair.c | 86 +++++++ .../string-anagram/string-anagram.c | 214 ++++++++++++++++++ .../subarray-sums/subarray-sums.c | 105 +++++++++ .../unexpected-demand/unexpected-demand.c | 78 +++++++ .../usernames-changes/usernames-changes.c | 88 +++++++ .../vowel-substring/vowel-substring.c | 115 ++++++++++ 13 files changed, 1549 insertions(+) create mode 100644 Problem-Solving-Basic/active-traders/active-traders.c create mode 100644 Problem-Solving-Basic/balanced-system-files-partition/balanced-system-files-partition.c create mode 100644 Problem-Solving-Basic/longest-subarray/longest-subarray.c create mode 100644 Problem-Solving-Basic/maximum-cost-of-laptop-count/maximum-cost-of-laptop-count.c create mode 100644 Problem-Solving-Basic/nearly-similar-rectangles/nearly-similar-rectangles.c create mode 100644 Problem-Solving-Basic/parallel-processing/parallel-processing.c create mode 100644 Problem-Solving-Basic/password-decryption/password-decryption.c create mode 100644 Problem-Solving-Basic/road-repair/road-repair.c create mode 100644 Problem-Solving-Basic/string-anagram/string-anagram.c create mode 100644 Problem-Solving-Basic/subarray-sums/subarray-sums.c create mode 100644 Problem-Solving-Basic/unexpected-demand/unexpected-demand.c create mode 100644 Problem-Solving-Basic/usernames-changes/usernames-changes.c create mode 100644 Problem-Solving-Basic/vowel-substring/vowel-substring.c diff --git a/Problem-Solving-Basic/active-traders/active-traders.c b/Problem-Solving-Basic/active-traders/active-traders.c new file mode 100644 index 0000000..dbab853 --- /dev/null +++ b/Problem-Solving-Basic/active-traders/active-traders.c @@ -0,0 +1,152 @@ +#include +#include +#include + +/* + * Complete the 'mostActive' function below. + * + * The function is expected to return a STRING_ARRAY. + * The function accepts STRING_ARRAY customers as parameter. + */ + +/* + * Algorithm: + * 1. Count the number of transactions for each unique customer: + * a. Iterate through all customer transactions + * b. For each customer, check if we've seen them before + * c. If not, add them to our unique customers list + * d. If yes, increment their transaction count + * 2. Filter customers with at least 5% of the total transactions: + * a. Calculate the threshold: 5% of total transactions + * b. Include only customers whose transaction count exceeds this threshold + * 3. Sort the filtered list of active traders alphabetically + * 4. Return the sorted list of active traders + * + * Time Complexity: + * - O(n²) for counting unique customers in the worst case + * - O(m log m) for sorting the active traders list + * Where n is the total number of transactions, m is the number of unique customers + * + * Space Complexity: O(m) where m is the number of unique customers + */ + +// Structure to store customer information +typedef struct +{ + char *name; + int count; +} CustomerInfo; + +// Comparison function for qsort (for alphabetical sorting) +int compareCustomers(const void *a, const void *b) +{ + return strcmp(((CustomerInfo *)a)->name, ((CustomerInfo *)b)->name); +} + +char **mostActive(int customers_count, char **customers, int *result_count) +{ + const int MAX_CUSTOMERS = 10000; // Maximum number of unique customers + CustomerInfo *unique_customers = (CustomerInfo *)malloc(MAX_CUSTOMERS * sizeof(CustomerInfo)); + int unique_count = 0; + + // Count occurrences of each customer + for (int i = 0; i < customers_count; i++) + { + // Check if customer already exists in our array + int found = 0; + for (int j = 0; j < unique_count; j++) + { + if (strcmp(unique_customers[j].name, customers[i]) == 0) + { + unique_customers[j].count++; + found = 1; + break; + } + } + + // If not found, add as a new customer + if (!found) + { + unique_customers[unique_count].name = strdup(customers[i]); + unique_customers[unique_count].count = 1; + unique_count++; + } + } + + // Create result array + char **result = (char **)malloc(unique_count * sizeof(char *)); + *result_count = 0; + + // Filter customers with >= 5% of transactions + float threshold = 0.05 * customers_count; + for (int i = 0; i < unique_count; i++) + { + if (unique_customers[i].count >= threshold) + { + result[*result_count] = strdup(unique_customers[i].name); + (*result_count)++; + } + } + + // Create a new array with just the active traders for sorting + CustomerInfo *active_traders = (CustomerInfo *)malloc(*result_count * sizeof(CustomerInfo)); + for (int i = 0; i < *result_count; i++) + { + active_traders[i].name = result[i]; + } + + // Sort active traders alphabetically + qsort(active_traders, *result_count, sizeof(CustomerInfo), compareCustomers); + + // Update result array with sorted names + for (int i = 0; i < *result_count; i++) + { + result[i] = active_traders[i].name; + } + + // Free memory + for (int i = 0; i < unique_count; i++) + { + free(unique_customers[i].name); + } + free(unique_customers); + free(active_traders); + + return result; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int customers_count; + scanf("%d", &customers_count); + + char **customers = malloc(customers_count * sizeof(char *)); + for (int i = 0; i < customers_count; i++) + { + customers[i] = malloc(101 * sizeof(char)); // Assuming max length of 100 + scanf("%s", customers[i]); + } + + int result_count; + char **result = mostActive(customers_count, customers, &result_count); + + for (int i = 0; i < result_count; i++) + { + fprintf(fptr, "%s\n", result[i]); + free(result[i]); + } + fprintf(fptr, "\n"); + + for (int i = 0; i < customers_count; i++) + { + free(customers[i]); + } + free(customers); + free(result); + + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/balanced-system-files-partition/balanced-system-files-partition.c b/Problem-Solving-Basic/balanced-system-files-partition/balanced-system-files-partition.c new file mode 100644 index 0000000..6161f10 --- /dev/null +++ b/Problem-Solving-Basic/balanced-system-files-partition/balanced-system-files-partition.c @@ -0,0 +1,117 @@ +#include +#include +#include + +/* + * Complete the 'mostBalancedPartition' function below. + * + * The function is expected to return an INTEGER. + * The function accepts following parameters: + * 1. INTEGER_ARRAY parent + * 2. INTEGER_ARRAY files_size + */ + +/* + * Algorithm: + * 1. Calculate the total size of each subtree in the file system tree: + * a. Use a recursive approach to sum up file sizes + * b. For each node, its total size = its own size + sizes of all child subtrees + * 2. Find the optimal partition point by: + * a. The system is divided into two parts by removing one edge from the tree + * b. When edge to node i is cut, we get subtree i and the rest of the tree + * c. Size of subtree i is size_sums[i] + * d. Size of the rest of the tree is total_size - size_sums[i] + * 3. Calculate the absolute difference between these two parts for each possible cut + * 4. Return the minimum difference found + * + * Time Complexity: O(n) where n is the number of nodes in the tree + * Space Complexity: O(n) for storing the size sums + */ + +// Recursive function to calculate size sums +long size_sums_rec(int node, int *parent, int *files_size, long *size_sums, int parent_count) +{ + // Calculate children first + for (int i = 0; i < parent_count; i++) + { + if (parent[i] == node) + { + size_sums[i] = size_sums_rec(i, parent, files_size, size_sums, parent_count); + } + } + + // Sum up this node's size plus all its children's sizes + long sum = files_size[node]; + for (int i = 0; i < parent_count; i++) + { + if (parent[i] == node) + { + sum += size_sums[i]; + } + } + + size_sums[node] = sum; + return sum; +} + +int mostBalancedPartition(int parent_count, int *parent, int files_size_count, int *files_size) +{ + // Allocate and initialize size_sums array + long *size_sums = (long *)malloc(parent_count * sizeof(long)); + for (int i = 0; i < parent_count; i++) + { + size_sums[i] = -1; // Initialize with -1 to indicate not calculated yet + } + + // Calculate size sums using recursion + size_sums_rec(0, parent, files_size, size_sums, parent_count); + + // Find the minimum absolute difference + long total_size = size_sums[0]; + long min_diff = LONG_MAX; + + for (int i = 1; i < parent_count; i++) + { + long diff = labs(total_size - 2 * size_sums[i]); + if (diff < min_diff) + { + min_diff = diff; + } + } + + free(size_sums); + return (int)min_diff; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int parent_count; + scanf("%d", &parent_count); + + int *parent = malloc(parent_count * sizeof(int)); + for (int i = 0; i < parent_count; i++) + { + scanf("%d", &parent[i]); + } + + int files_size_count; + scanf("%d", &files_size_count); + + int *files_size = malloc(files_size_count * sizeof(int)); + for (int i = 0; i < files_size_count; i++) + { + scanf("%d", &files_size[i]); + } + + int result = mostBalancedPartition(parent_count, parent, files_size_count, files_size); + + fprintf(fptr, "%d\n", result); + + free(parent); + free(files_size); + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/longest-subarray/longest-subarray.c b/Problem-Solving-Basic/longest-subarray/longest-subarray.c new file mode 100644 index 0000000..abe065d --- /dev/null +++ b/Problem-Solving-Basic/longest-subarray/longest-subarray.c @@ -0,0 +1,115 @@ +#include +#include + +/* + * Complete the 'longestSubarray' function below. + * + * The function is expected to return an INTEGER. + * The function accepts INTEGER_ARRAY arr as parameter. + */ + +/* + * Algorithm: + * 1. For each possible starting position: + * a. Try to form a subarray with at most 2 distinct values + * b. Additionally, the two values must differ by at most 1 + * 2. Use a window expansion approach: + * a. Track distinct values seen so far (at most 2) + * b. When a new value is encountered, check if it can be added: + * i. If we have 0 values so far, add it + * ii. If we have 1 value so far, add it if |new_val - existing_val| ≤ 1 + * iii. If we have 2 values already, check if the new value matches either + * c. If a value can't be added, the window can't be expanded further + * 3. Track the maximum valid window length + * + * Time Complexity: O(n²) where n is the array length + * Space Complexity: O(1) additional space + */ + +int longestSubarray(int arr_count, int *arr) +{ + int ans = 0; + + // O(n^2) is okay because of constraints. + for (int i = 0; i < arr_count; i++) + { + int w[2] = {-1, -1}; // Stores the two distinct values (-1 means empty) + int w_count = 0; // Number of distinct values stored + int cnt = 0; // Length of current subarray + + for (int j = i; j < arr_count; j++) + { + // Check if current element matches either of the two values + if (w_count > 0 && arr[j] == w[0]) + { + cnt++; + continue; + } + + if (w_count > 1 && arr[j] == w[1]) + { + cnt++; + continue; + } + + // If we don't have any value yet, add this as first + if (w_count == 0) + { + w[0] = arr[j]; + w_count = 1; + cnt++; + } + // If we have only one value, check if new value can be added + else if (w_count == 1) + { + if (abs(w[0] - arr[j]) <= 1) + { + w[1] = arr[j]; + w_count = 2; + cnt++; + } + else + { + // If difference > 1, we can't add this element + break; + } + } + // If we already have two values, and this is a third distinct value, break + else + { + break; + } + } + + // Update answer with max subarray length found + if (cnt > ans) + { + ans = cnt; + } + } + + return ans; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int arr_count; + scanf("%d", &arr_count); + + int *arr = malloc(arr_count * sizeof(int)); + for (int i = 0; i < arr_count; i++) + { + scanf("%d", &arr[i]); + } + + int result = longestSubarray(arr_count, arr); + + fprintf(fptr, "%d\n", result); + + free(arr); + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/maximum-cost-of-laptop-count/maximum-cost-of-laptop-count.c b/Problem-Solving-Basic/maximum-cost-of-laptop-count/maximum-cost-of-laptop-count.c new file mode 100644 index 0000000..be1b7f1 --- /dev/null +++ b/Problem-Solving-Basic/maximum-cost-of-laptop-count/maximum-cost-of-laptop-count.c @@ -0,0 +1,107 @@ +#include +#include +#include + +/* + * Complete the 'maxCost' function below. + * + * The function is expected to return an INTEGER. + * The function accepts following parameters: + * 1. INTEGER_ARRAY cost + * 2. STRING_ARRAY labels + * 3. INTEGER dailyCount + */ + +/* + * Algorithm: + * 1. Process laptops in order, tracking both cost and the count of legal laptops + * 2. For each laptop: + * a. Add its cost to the current batch's cost accumulator + * b. If the laptop is 'legal', increment the legal count + * 3. When we reach exactly 'dailyCount' legal laptops: + * a. Compare the current batch's total cost with the maximum seen so far + * b. Update the maximum cost if current batch is more expensive + * c. Reset the counters to start a new batch + * 4. Return the maximum cost found + * + * Time Complexity: O(n) where n is the number of laptops + * Space Complexity: O(1) additional space (not counting input/output) + */ + +int maxCost(int cost_count, int *cost, char **labels, int dailyCount) +{ + int ans = 0; + int cur_cnt = 0; + int cur_cost = 0; + + for (int i = 0; i < cost_count; i++) + { + cur_cost += cost[i]; + + // Skip illegal labels + if (strcmp(labels[i], "illegal") == 0) + { + continue; + } + + cur_cnt++; + + // Check if we've reached the daily count + if (cur_cnt == dailyCount) + { + // Update answer if current cost is greater + if (cur_cost > ans) + { + ans = cur_cost; + } + + // Reset counters for the next batch + cur_cnt = 0; + cur_cost = 0; + } + } + + return ans; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int cost_count; + scanf("%d", &cost_count); + + int *cost = malloc(cost_count * sizeof(int)); + for (int i = 0; i < cost_count; i++) + { + scanf("%d", &cost[i]); + } + + int labels_count; + scanf("%d", &labels_count); + + char **labels = malloc(labels_count * sizeof(char *)); + for (int i = 0; i < labels_count; i++) + { + labels[i] = malloc(8 * sizeof(char)); // "illegal" or "legal" + null terminator + scanf("%s", labels[i]); + } + + int dailyCount; + scanf("%d", &dailyCount); + + int result = maxCost(cost_count, cost, labels, dailyCount); + + fprintf(fptr, "%d\n", result); + + for (int i = 0; i < labels_count; i++) + { + free(labels[i]); + } + free(labels); + free(cost); + + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/nearly-similar-rectangles/nearly-similar-rectangles.c b/Problem-Solving-Basic/nearly-similar-rectangles/nearly-similar-rectangles.c new file mode 100644 index 0000000..be15880 --- /dev/null +++ b/Problem-Solving-Basic/nearly-similar-rectangles/nearly-similar-rectangles.c @@ -0,0 +1,158 @@ +#include +#include +#include + +/* + * Complete the 'nearlySimilarRectangles' function below. + * + * The function is expected to return a LONG_INTEGER. + * The function accepts 2D_LONG_INTEGER_ARRAY sides as parameter. + */ + +/* + * Algorithm: + * 1. Two rectangles are "nearly similar" if their width-to-height ratios are the same + * 2. For each rectangle, normalize its ratio by: + * a. Finding the GCD (greatest common divisor) of width and height + * b. Dividing both width and height by their GCD + * 3. Use a hash table to group rectangles with the same normalized ratio + * 4. For each group, calculate the number of pairs using the formula n*(n-1)/2 + * where n is the number of rectangles in the group + * 5. Sum up the pairs from all groups + * + * Optimization: + * - Instead of calculating pairs afterward, we count them during insertion + * by adding the current count of matching ratios to our result + * + * Time Complexity: O(n * log(max(w,h))) where: + * - n is the number of rectangles + * - w, h are the maximum width and height values + * - log term is from GCD calculation + * Space Complexity: O(n) for the hash table + */ + +// Calculate GCD (Greatest Common Divisor) +long gcd(long a, long b) +{ + if (b == 0) + return a; + return gcd(b, a % b); +} + +// Structure for storing normalized ratios +struct Ratio +{ + long width; + long height; +}; + +// Hash table entry +struct Entry +{ + struct Ratio ratio; + int count; + struct Entry *next; +}; + +// Simple hash function +unsigned long hash(long w, long h) +{ + return (w * 31 + h) % 10007; // Prime number +} + +long nearlySimilarRectangles(int sides_rows, long **sides) +{ + const int TABLE_SIZE = 10007; // Prime number for hash table + struct Entry **table = (struct Entry **)calloc(TABLE_SIZE, sizeof(struct Entry *)); + + long result = 0; + + for (int i = 0; i < sides_rows; i++) + { + long w = sides[i][0]; + long h = sides[i][1]; + + // Calculate GCD to normalize ratio + long g = gcd(w, h); + w /= g; + h /= g; + + // Hash the normalized ratio + unsigned long h_val = hash(w, h); + + // Check if this ratio already exists + struct Entry *entry = table[h_val]; + int found = 0; + + while (entry != NULL) + { + if (entry->ratio.width == w && entry->ratio.height == h) + { + // Found matching ratio, add to count and calculate new pairs + result += entry->count; + entry->count++; + found = 1; + break; + } + entry = entry->next; + } + + // If not found, add new entry + if (!found) + { + struct Entry *new_entry = (struct Entry *)malloc(sizeof(struct Entry)); + new_entry->ratio.width = w; + new_entry->ratio.height = h; + new_entry->count = 1; + new_entry->next = table[h_val]; + table[h_val] = new_entry; + } + } + + // Clean up the hash table + for (int i = 0; i < TABLE_SIZE; i++) + { + struct Entry *entry = table[i]; + while (entry != NULL) + { + struct Entry *temp = entry; + entry = entry->next; + free(temp); + } + } + free(table); + + return result; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int sides_rows, sides_columns; + scanf("%d %d", &sides_rows, &sides_columns); + + long **sides = (long **)malloc(sides_rows * sizeof(long *)); + for (int i = 0; i < sides_rows; i++) + { + sides[i] = (long *)malloc(sides_columns * sizeof(long)); + for (int j = 0; j < sides_columns; j++) + { + scanf("%ld", &sides[i][j]); + } + } + + long result = nearlySimilarRectangles(sides_rows, sides); + + fprintf(fptr, "%ld\n", result); + + for (int i = 0; i < sides_rows; i++) + { + free(sides[i]); + } + free(sides); + + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/parallel-processing/parallel-processing.c b/Problem-Solving-Basic/parallel-processing/parallel-processing.c new file mode 100644 index 0000000..b0bbdb3 --- /dev/null +++ b/Problem-Solving-Basic/parallel-processing/parallel-processing.c @@ -0,0 +1,115 @@ +#include +#include + +/* + * Complete the 'minTime' function below. + * + * The function is expected to return a LONG_INTEGER. + * The function accepts following parameters: + * 1. INTEGER_ARRAY files + * 2. INTEGER numCores + * 3. INTEGER limit + */ + +/* + * Algorithm: + * 1. Separate files into two groups: + * a. Files divisible by numCores (can benefit from parallel processing) + * b. Files not divisible by numCores (no benefit from parallel processing) + * 2. Sort divisible files in descending order to prioritize larger files for optimization + * 3. Apply parallel processing to at most 'limit' files from the divisible group + * (divide processing time by numCores for these files) + * 4. Process the rest of the files with single-core processing + * 5. Sum up all processing times + * + * Intuition: + * - Parallel processing is most beneficial for larger files that are divisible by numCores + * - Using parallel processing on non-divisible files gives no advantage + * - Sort to ensure we use the limited parallel slots for the largest possible files + * + * Time Complexity: O(n log n) due to sorting + * Space Complexity: O(n) for storing the separated arrays + */ + +// Comparison function for qsort (descending order) +int compare_desc(const void *a, const void *b) +{ + return (*(int *)b - *(int *)a); +} + +long minTime(int files_count, int *files, int numCores, int limit) +{ + int *divisible = (int *)malloc(files_count * sizeof(int)); + int *not_divisible = (int *)malloc(files_count * sizeof(int)); + int div_count = 0, not_div_count = 0; + + // Separate files into divisible and not divisible by numCores + for (int i = 0; i < files_count; i++) + { + if (files[i] % numCores == 0) + { + divisible[div_count++] = files[i]; + } + else + { + not_divisible[not_div_count++] = files[i]; + } + } + + // Sort divisible files in descending order + qsort(divisible, div_count, sizeof(int), compare_desc); + + // Calculate total time + long total_time = 0; + + // Process limited number of files with parallel processing + for (int i = 0; i < div_count; i++) + { + if (i < limit) + { + total_time += divisible[i] / numCores; + } + else + { + total_time += divisible[i]; + } + } + + // Add time for non-divisible files (no benefit from parallel processing) + for (int i = 0; i < not_div_count; i++) + { + total_time += not_divisible[i]; + } + + free(divisible); + free(not_divisible); + + return total_time; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int files_count; + scanf("%d", &files_count); + + int *files = (int *)malloc(files_count * sizeof(int)); + for (int i = 0; i < files_count; i++) + { + scanf("%d", &files[i]); + } + + int numCores, limit; + scanf("%d", &numCores); + scanf("%d", &limit); + + long result = minTime(files_count, files, numCores, limit); + + fprintf(fptr, "%ld\n", result); + + free(files); + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/password-decryption/password-decryption.c b/Problem-Solving-Basic/password-decryption/password-decryption.c new file mode 100644 index 0000000..4778e3c --- /dev/null +++ b/Problem-Solving-Basic/password-decryption/password-decryption.c @@ -0,0 +1,99 @@ +#include +#include +#include + +/* + * Complete the 'decryptPassword' function below. + * + * The function is expected to return a STRING. + * The function accepts STRING s as parameter. + */ + +/* + * Algorithm: + * 1. The password is encrypted with three operations: + * a. Digits are placed at the beginning and replaced with '0' in the original position + * b. Characters around '*' are swapped + * c. '*' is added to mark the swapped positions + * + * To decrypt: + * 1. Identify the digits at the beginning of the encrypted password + * 2. Replace '0's in the string with those digits in reverse order + * 3. For each '*', swap the two preceding characters + * 4. Remove placeholder characters (digits at beginning and '*') + * + * Time Complexity: O(n) where n is the length of the encrypted password + * Space Complexity: O(n) for storing the decrypted password + */ + +char *decryptPassword(char *s) +{ + int len = strlen(s); + char *result = (char *)malloc((len + 1) * sizeof(char)); + char *temp = (char *)malloc((len + 1) * sizeof(char)); + + strcpy(temp, s); + + int i = 0; + // Find where numeric prefix ends + while (i < len && temp[i] >= '1' && temp[i] <= '9') + { + i++; + } + + // Replace 0's with corresponding digits + int j; + int digit_index = i - 1; + for (j = i; j < len; j++) + { + if (temp[j] == '0' && digit_index >= 0) + { + temp[j] = temp[digit_index]; + temp[digit_index] = ' '; // Mark as used + digit_index--; + } + } + + // Swap characters around '*' + for (j = i; j < len; j++) + { + if (temp[j] == '*') + { + char t = temp[j - 1]; + temp[j - 1] = temp[j - 2]; + temp[j - 2] = t; + } + } + + // Build result string by copying non-space and non-* characters + int result_index = 0; + for (j = i; j < len; j++) + { + if (temp[j] != ' ' && temp[j] != '*') + { + result[result_index++] = temp[j]; + } + } + + result[result_index] = '\0'; + free(temp); + return result; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + char *s = (char *)malloc(10001 * sizeof(char)); + scanf("%s", s); + + char *result = decryptPassword(s); + + fprintf(fptr, "%s\n", result); + + free(s); + free(result); + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/road-repair/road-repair.c b/Problem-Solving-Basic/road-repair/road-repair.c new file mode 100644 index 0000000..9d2e5d6 --- /dev/null +++ b/Problem-Solving-Basic/road-repair/road-repair.c @@ -0,0 +1,86 @@ +#include +#include +#include + +/* + * Complete the 'getMinCost' function below. + * + * The function is expected to return a LONG_INTEGER. + * The function accepts following parameters: + * 1. INTEGER_ARRAY crew_id + * 2. INTEGER_ARRAY job_id + */ + +/* + * Algorithm: + * 1. Sort both crew_id and job_id arrays in ascending order + * 2. Pair each crew with the job having the same relative position after sorting + * (i.e., the crew with the smallest ID with the job with the smallest ID, etc.) + * 3. For each pair, calculate the absolute difference between crew_id and job_id + * 4. Sum up all these absolute differences to get the total cost + * + * Intuition: + * - Sorting both arrays minimizes the sum of absolute differences when pairing + * elements at matching positions + * - This is optimal because any other pairing would lead to greater differences + * + * Time Complexity: O(n log n) due to sorting + * Space Complexity: O(1) additional space (not counting input/output) + */ + +// Compare function for qsort +int compare(const void *a, const void *b) +{ + return (*(int *)a - *(int *)b); +} + +long getMinCost(int crew_id_count, int *crew_id, int job_id_count, int *job_id) +{ + // Sort both arrays + qsort(crew_id, crew_id_count, sizeof(int), compare); + qsort(job_id, job_id_count, sizeof(int), compare); + + // Calculate sum of absolute differences + long total_cost = 0; + for (int i = 0; i < crew_id_count; i++) + { + total_cost += labs((long)crew_id[i] - (long)job_id[i]); + } + + return total_cost; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int crew_id_count; + scanf("%d", &crew_id_count); + + int *crew_id = malloc(crew_id_count * sizeof(int)); + + for (int i = 0; i < crew_id_count; i++) + { + scanf("%d", &crew_id[i]); + } + + int job_id_count; + scanf("%d", &job_id_count); + + int *job_id = malloc(job_id_count * sizeof(int)); + + for (int i = 0; i < job_id_count; i++) + { + scanf("%d", &job_id[i]); + } + + long result = getMinCost(crew_id_count, crew_id, job_id_count, job_id); + + fprintf(fptr, "%ld\n", result); + + fclose(fptr); + free(crew_id); + free(job_id); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/string-anagram/string-anagram.c b/Problem-Solving-Basic/string-anagram/string-anagram.c new file mode 100644 index 0000000..5212a4e --- /dev/null +++ b/Problem-Solving-Basic/string-anagram/string-anagram.c @@ -0,0 +1,214 @@ +#include +#include +#include + +/* + * Complete the 'stringAnagram' function below. + * + * The function is expected to return an INTEGER_ARRAY. + * The function accepts following parameters: + * 1. STRING_ARRAY dictionary + * 2. STRING_ARRAY query + */ + +/* + * Algorithm: + * 1. Create a hash table to store sorted words from the dictionary: + * a. For each word in the dictionary, sort its characters + * b. Use the sorted word as a key, and count how many words map to the same sorted form + * 2. For each query word: + * a. Sort the query word + * b. Look up the sorted word in the hash table + * c. Return the count of matching words (or 0 if none found) + * + * Note: A hash table is used for efficient lookups. Two words are anagrams if they have the same sorted order. + * + * Time Complexity: O(n*m log m + q*k log k) where: + * - n is the number of dictionary words + * - m is the maximum length of a dictionary word + * - q is the number of query words + * - k is the maximum length of a query word + * Space Complexity: O(n) for storing the hash table + */ + +// Function to sort a string +void sortString(char *str) +{ + int n = strlen(str); + char temp; + + for (int i = 0; i < n - 1; i++) + { + for (int j = i + 1; j < n; j++) + { + if (str[i] > str[j]) + { + temp = str[i]; + str[i] = str[j]; + str[j] = temp; + } + } + } +} + +// Structure for dictionary entries +struct DictEntry +{ + char *sorted_word; + int count; +}; + +// Simple hash function for strings +unsigned long hash(char *str) +{ + unsigned long hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +int *stringAnagram(int dictionary_count, char **dictionary, int query_count, char **query) +{ + // Create a structure to store dictionary entries + const int TABLE_SIZE = 10007; // Prime number for hash table + struct DictEntry **table = (struct DictEntry **)calloc(TABLE_SIZE, sizeof(struct DictEntry *)); + + // Process dictionary words + for (int i = 0; i < dictionary_count; i++) + { + // Create a copy to sort + int len = strlen(dictionary[i]); + char *sorted = (char *)malloc((len + 1) * sizeof(char)); + strcpy(sorted, dictionary[i]); + sortString(sorted); + + // Hash the sorted word + unsigned long h = hash(sorted) % TABLE_SIZE; + + // Find if this sorted word already exists in our table + int found = 0; + struct DictEntry *entry = table[h]; + while (entry != NULL) + { + if (strcmp(entry->sorted_word, sorted) == 0) + { + entry->count++; + found = 1; + break; + } + entry = entry->count > 0 ? (struct DictEntry *)entry->sorted_word : NULL; // Use count field as next pointer + } + + // If not found, add new entry + if (!found) + { + struct DictEntry *new_entry = (struct DictEntry *)malloc(sizeof(struct DictEntry)); + new_entry->sorted_word = sorted; + new_entry->count = 1; + // Insert at the head of the chain + if (table[h] != NULL) + { + entry = (struct DictEntry *)table[h]->sorted_word; + table[h]->sorted_word = (char *)new_entry; + } + else + { + table[h] = new_entry; + } + } + else + { + free(sorted); // We don't need this copy + } + } + + // Process queries + int *result = (int *)calloc(query_count, sizeof(int)); + + for (int i = 0; i < query_count; i++) + { + // Sort the query word + int len = strlen(query[i]); + char *sorted = (char *)malloc((len + 1) * sizeof(char)); + strcpy(sorted, query[i]); + sortString(sorted); + + // Look up in the hash table + unsigned long h = hash(sorted) % TABLE_SIZE; + struct DictEntry *entry = table[h]; + + while (entry != NULL) + { + if (strcmp(entry->sorted_word, sorted) == 0) + { + result[i] = entry->count; + break; + } + entry = entry->count > 0 ? (struct DictEntry *)entry->sorted_word : NULL; + } + + free(sorted); + } + + // Clean up the hash table + for (int i = 0; i < TABLE_SIZE; i++) + { + struct DictEntry *entry = table[i]; + while (entry != NULL) + { + struct DictEntry *next = entry->count > 0 ? (struct DictEntry *)entry->sorted_word : NULL; + free(entry->sorted_word); + free(entry); + entry = next; + } + } + free(table); + + return result; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int dictionary_count; + scanf("%d", &dictionary_count); + + char **dictionary = (char **)malloc(dictionary_count * sizeof(char *)); + for (int i = 0; i < dictionary_count; i++) + { + dictionary[i] = (char *)malloc(1001 * sizeof(char)); + scanf("%s", dictionary[i]); + } + + int query_count; + scanf("%d", &query_count); + + char **query = (char **)malloc(query_count * sizeof(char *)); + for (int i = 0; i < query_count; i++) + { + query[i] = (char *)malloc(1001 * sizeof(char)); + scanf("%s", query[i]); + } + + int *result = stringAnagram(dictionary_count, dictionary, query_count, query); + + for (int i = 0; i < query_count; i++) + { + fprintf(fptr, "%d\n", result[i]); + free(query[i]); + free(dictionary[i]); + } + fprintf(fptr, "\n"); + + free(dictionary); + free(query); + free(result); + + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/subarray-sums/subarray-sums.c b/Problem-Solving-Basic/subarray-sums/subarray-sums.c new file mode 100644 index 0000000..838f234 --- /dev/null +++ b/Problem-Solving-Basic/subarray-sums/subarray-sums.c @@ -0,0 +1,105 @@ +#include +#include + +/* + * Complete the 'findSum' function below. + * + * The function is expected to return a LONG_INTEGER_ARRAY. + * The function accepts following parameters: + * 1. INTEGER_ARRAY numbers + * 2. 2D_INTEGER_ARRAY queries + */ + +/* + * Algorithm: + * 1. Use prefix sum technique to efficiently calculate subarray sums + * 2. Create two prefix arrays: + * a. prefix_sum: For computing regular subarray sums + * b. zero_count: For tracking the number of zeros in a prefix + * 3. For each query (l, r, x): + * a. Calculate regular sum using prefix_sum: prefix_sum[r] - prefix_sum[l-1] + * b. Find zeros in range using zero_count: zero_count[r] - zero_count[l-1] + * c. Add x * (zeros in range) to the sum + * 4. Return results for all queries + * + * Time Complexity: O(n + q) where n is the array length and q is number of queries + * Space Complexity: O(n) for prefix sum arrays + */ + +long *findSum(int numbers_count, int *numbers, int queries_rows, int **queries) +{ + long *prefix_sum = (long *)malloc((numbers_count + 1) * sizeof(long)); + int *zero_count = (int *)malloc((numbers_count + 1) * sizeof(int)); + long *result = (long *)malloc(queries_rows * sizeof(long)); + + prefix_sum[0] = 0; + zero_count[0] = 0; + + // Precompute prefix sum and zero count + for (int i = 0; i < numbers_count; i++) + { + prefix_sum[i + 1] = prefix_sum[i] + numbers[i]; + zero_count[i + 1] = zero_count[i] + (numbers[i] == 0); + } + + // Process each query + for (int i = 0; i < queries_rows; i++) + { + int l = queries[i][0]; + int r = queries[i][1]; + int x = queries[i][2]; + + // Calculate sum and add x * count of zeros + result[i] = (prefix_sum[r] - prefix_sum[l - 1]) + (x * (zero_count[r] - zero_count[l - 1])); + } + + free(prefix_sum); + free(zero_count); + + return result; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int numbers_count; + scanf("%d", &numbers_count); + + int *numbers = (int *)malloc(numbers_count * sizeof(int)); + for (int i = 0; i < numbers_count; i++) + { + scanf("%d", &numbers[i]); + } + + int queries_rows; + int queries_columns; + scanf("%d %d", &queries_rows, &queries_columns); + + int **queries = (int **)malloc(queries_rows * sizeof(int *)); + for (int i = 0; i < queries_rows; i++) + { + queries[i] = (int *)malloc(queries_columns * sizeof(int)); + for (int j = 0; j < queries_columns; j++) + { + scanf("%d", &queries[i][j]); + } + } + + long *result = findSum(numbers_count, numbers, queries_rows, queries); + + for (int i = 0; i < queries_rows; i++) + { + fprintf(fptr, "%ld\n", result[i]); + free(queries[i]); + } + fprintf(fptr, "\n"); + + free(numbers); + free(queries); + free(result); + + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/unexpected-demand/unexpected-demand.c b/Problem-Solving-Basic/unexpected-demand/unexpected-demand.c new file mode 100644 index 0000000..cb7c2f6 --- /dev/null +++ b/Problem-Solving-Basic/unexpected-demand/unexpected-demand.c @@ -0,0 +1,78 @@ +#include +#include + +/* + * Complete the 'filledOrders' function below. + * + * The function is expected to return an INTEGER. + * The function accepts following parameters: + * 1. INTEGER_ARRAY order + * 2. INTEGER k + */ + +/* + * Algorithm: + * 1. Sort the orders by size (smallest first) + * 2. Process orders in ascending order: + * a. If we have enough capacity (k) to fulfill an order, fulfill it + * b. Decrement the remaining capacity by the order size + * c. If we don't have enough capacity, break + * 3. Return the number of orders fulfilled + * + * Time Complexity: O(n log n) due to sorting + * Space Complexity: O(1) extra space (not counting input) + */ + +// Comparison function for qsort +int compare(const void *a, const void *b) +{ + return (*(int *)a - *(int *)b); +} + +int filledOrders(int order_count, int *order, int k) +{ + // Sort the order array + qsort(order, order_count, sizeof(int), compare); + + int ans = 0; + for (int i = 0; i < order_count; i++) + { + if (order[i] <= k) + { + ans++; + k -= order[i]; + } + else + { + break; + } + } + return ans; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int order_count; + scanf("%d", &order_count); + + int *order = malloc(order_count * sizeof(int)); + + for (int i = 0; i < order_count; i++) + { + scanf("%d", &order[i]); + } + + int k; + scanf("%d", &k); + + int result = filledOrders(order_count, order, k); + + fprintf(fptr, "%d\n", result); + + fclose(fptr); + free(order); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/usernames-changes/usernames-changes.c b/Problem-Solving-Basic/usernames-changes/usernames-changes.c new file mode 100644 index 0000000..7b74e79 --- /dev/null +++ b/Problem-Solving-Basic/usernames-changes/usernames-changes.c @@ -0,0 +1,88 @@ +#include +#include +#include + +/* + * Complete the 'possibleChanges' function below. + * + * The function is expected to return a STRING_ARRAY. + * The function accepts STRING_ARRAY usernames as parameter. + */ + +/* + * Algorithm: + * 1. For each username, check if we can create a lexicographically smaller name + * 2. A username can be made lexicographically smaller if there exists two characters + * where a character at index i is greater than a character at index j, where i < j + * 3. If such a pair exists, swap them to get a smaller username (though we don't actually do the swap) + * 4. For each username, return "YES" if such a swap is possible, "NO" otherwise + * + * Time Complexity: O(n * m^2) where n is the number of usernames and m is the max length of a username + * Space Complexity: O(n) for storing the results + */ + +char **possibleChanges(int usernames_count, char **usernames) +{ + char **ans = (char **)malloc(usernames_count * sizeof(char *)); + + for (int i = 0; i < usernames_count; i++) + { + ans[i] = (char *)malloc(4 * sizeof(char)); // "YES" or "NO" plus null terminator + + if (strlen(usernames[i]) <= 1) + { + strcpy(ans[i], "NO"); + continue; + } + + int found = 0; + for (int j = 0; j < strlen(usernames[i]) - 1; j++) + { + if (usernames[i][j] > usernames[i][j + 1]) + { + strcpy(ans[i], "YES"); + found = 1; + break; + } + } + + if (!found) + { + strcpy(ans[i], "NO"); + } + } + + return ans; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + int usernames_count; + scanf("%d", &usernames_count); + + char **usernames = (char **)malloc(usernames_count * sizeof(char *)); + + for (int i = 0; i < usernames_count; i++) + { + usernames[i] = (char *)malloc(1001 * sizeof(char)); + scanf("%s", usernames[i]); + } + + char **result = possibleChanges(usernames_count, usernames); + + for (int i = 0; i < usernames_count; i++) + { + fprintf(fptr, "%s\n", result[i]); + free(result[i]); + free(usernames[i]); + } + + free(result); + free(usernames); + + fclose(fptr); + + return 0; +} \ No newline at end of file diff --git a/Problem-Solving-Basic/vowel-substring/vowel-substring.c b/Problem-Solving-Basic/vowel-substring/vowel-substring.c new file mode 100644 index 0000000..75abc22 --- /dev/null +++ b/Problem-Solving-Basic/vowel-substring/vowel-substring.c @@ -0,0 +1,115 @@ +#include +#include +#include + +/* + * Complete the 'findSubstring' function below. + * + * The function is expected to return a STRING. + * The function accepts following parameters: + * 1. STRING s + * 2. INTEGER k + */ + +/* + * Algorithm: + * 1. Define a sliding window of size k and count vowels in this window + * 2. Initialize first window by counting vowels in first k characters + * 3. Slide the window through the string: + * a. Add new character (rightmost in window) + * b. Remove old character (leftmost in previous window) + * c. Check if current window has more vowels than the best found so far + * 4. Return the substring with maximum vowels, or "Not found!" if no vowels exist + * + * Time Complexity: O(n) where n is the length of string s + * Space Complexity: O(k) for storing the result substring + */ + +char *findSubstring(char *s, int k) +{ + char vowels[] = "aeiou"; + int len = strlen(s); + int best = 0, ans = 0; + int i, j; + + // Initialize the first window + int cur = 0; + for (i = 0; i < k && i < len; i++) + { + for (j = 0; j < 5; j++) + { + if (s[i] == vowels[j]) + { + cur++; + break; + } + } + } + + best = cur; + + // Slide the window + for (i = k; i < len; i++) + { + // Add new character + for (j = 0; j < 5; j++) + { + if (s[i] == vowels[j]) + { + cur++; + break; + } + } + + // Remove old character + for (j = 0; j < 5; j++) + { + if (s[i - k] == vowels[j]) + { + cur--; + break; + } + } + + if (cur > best) + { + best = cur; + ans = i - k + 1; + } + } + + // Allocate memory for result string + char *result = (char *)malloc((k + 1) * sizeof(char)); + if (best > 0) + { + strncpy(result, &s[ans], k); + result[k] = '\0'; + } + else + { + strcpy(result, "Not found!"); + } + + return result; +} + +int main() +{ + FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); + + char *s = malloc(200001 * sizeof(char)); + scanf("%s", s); + + int k; + scanf("%d", &k); + + char *result = findSubstring(s, k); + + fprintf(fptr, "%s\n", result); + + fclose(fptr); + free(s); + free(result); + + return 0; +} \ No newline at end of file From 0dbd8a830a869255670ba586dc9b6616971e91ee Mon Sep 17 00:00:00 2001 From: snigenigmatic Date: Fri, 25 Apr 2025 06:40:27 +0530 Subject: [PATCH 2/2] minor changes --- Problem-Solving-Basic/longest-subarray/longest-subarray.c | 1 - .../maximum-cost-of-laptop-count.c | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Problem-Solving-Basic/longest-subarray/longest-subarray.c b/Problem-Solving-Basic/longest-subarray/longest-subarray.c index abe065d..5ec0234 100644 --- a/Problem-Solving-Basic/longest-subarray/longest-subarray.c +++ b/Problem-Solving-Basic/longest-subarray/longest-subarray.c @@ -94,7 +94,6 @@ int longestSubarray(int arr_count, int *arr) int main() { FILE *fptr = fopen(getenv("OUTPUT_PATH"), "w"); - int arr_count; scanf("%d", &arr_count); diff --git a/Problem-Solving-Basic/maximum-cost-of-laptop-count/maximum-cost-of-laptop-count.c b/Problem-Solving-Basic/maximum-cost-of-laptop-count/maximum-cost-of-laptop-count.c index be1b7f1..a602f32 100644 --- a/Problem-Solving-Basic/maximum-cost-of-laptop-count/maximum-cost-of-laptop-count.c +++ b/Problem-Solving-Basic/maximum-cost-of-laptop-count/maximum-cost-of-laptop-count.c @@ -28,11 +28,12 @@ * Space Complexity: O(1) additional space (not counting input/output) */ -int maxCost(int cost_count, int *cost, char **labels, int dailyCount) +int maxCost(int *cost, char **labels, int dailyCount) { int ans = 0; int cur_cnt = 0; int cur_cost = 0; + int cost_count = sizeof(cost) / sizeof(cost[0]); for (int i = 0; i < cost_count; i++) {