|
| 1 | +/* |
| 2 | + * Copyright (C) 2022, Saul Lawliet <october dot sunbathe at gmail dot com> |
| 3 | + * All rights reserved. |
| 4 | + * |
| 5 | + * 尝试用朴素方法, 排序之后, 从头开始处理, 移除头部, 二分查找double. 提交后超时... |
| 6 | + * 写下上句话的时候, 突然想出一个优化方法, 按"块"的二分查找 |
| 7 | + * |
| 8 | + * ... |
| 9 | + * |
| 10 | + * 提交后依然失败, 看来只能换个思路了 |
| 11 | + */ |
| 12 | + |
| 13 | +#include "c/data-structures/array.h" |
| 14 | +#include "c/test.h" |
| 15 | +#include "c/tools/compare.h" |
| 16 | + |
| 17 | +/** [p, q], return index */ |
| 18 | +int binarySearch(int *arr, int p, int q, int target) { |
| 19 | + while (p <= q) { |
| 20 | + int mid = p + (q - p) / 2; |
| 21 | + if (target < arr[mid]) { |
| 22 | + q = mid - 1; |
| 23 | + } else if (target > arr[mid]) { |
| 24 | + p = mid + 1; |
| 25 | + } else { |
| 26 | + // 找到第一个的匹配 |
| 27 | + if ((mid == 0) || (arr[mid - 1] != target)) |
| 28 | + return mid; |
| 29 | + else |
| 30 | + q = mid - 1; |
| 31 | + } |
| 32 | + } |
| 33 | + return -1; |
| 34 | +} |
| 35 | + |
| 36 | +/** |
| 37 | + * Note: The returned array must be malloced, assume caller calls free(). |
| 38 | + */ |
| 39 | +int *findOriginalArray(int *changed, int changedSize, int *returnSize) { |
| 40 | + *returnSize = 0; |
| 41 | + int *returnArray = malloc(sizeof(int) * (changedSize / 2)); |
| 42 | + if (changedSize % 2 == 1) return returnArray; // 长度是奇数, 一定不正确 |
| 43 | + |
| 44 | + // 排好序, 方便处理 |
| 45 | + qsort(changed, changedSize, sizeof(int), compare_ints); |
| 46 | + |
| 47 | + int skipHead = 0; // 减少删除数组头部, 设置的变量 |
| 48 | + |
| 49 | + while (changedSize - skipHead > 0) { |
| 50 | + int first = changed[skipHead]; |
| 51 | + int countFirst = 0; |
| 52 | + while (skipHead + countFirst < changedSize && changed[skipHead + countFirst] == first) { |
| 53 | + countFirst++; |
| 54 | + } |
| 55 | + |
| 56 | + // 0 需要特殊处理一下 |
| 57 | + int doubleIndex; |
| 58 | + if (first == 0 && countFirst % 2 == 0) { |
| 59 | + countFirst /= 2; |
| 60 | + doubleIndex = skipHead + countFirst; |
| 61 | + } else { |
| 62 | + doubleIndex = binarySearch(changed, skipHead + countFirst, changedSize - 1, first * 2); |
| 63 | + if (doubleIndex == -1) { |
| 64 | + // 如果找不到 double, 那么失败 |
| 65 | + *returnSize = 0; |
| 66 | + return returnArray; |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + |
| 71 | + for (int i = 0; i < countFirst; i++) { |
| 72 | + if (doubleIndex + i >= changedSize || changed[doubleIndex+i] != first * 2) { |
| 73 | + *returnSize = 0; |
| 74 | + return returnArray; |
| 75 | + } |
| 76 | + // 保存 original |
| 77 | + returnArray[(*returnSize)++] = first; |
| 78 | + skipHead++; |
| 79 | + } |
| 80 | + |
| 81 | + // 删除 double |
| 82 | + if (doubleIndex == skipHead) { |
| 83 | + skipHead += countFirst; // 如果恰好是第一个, 那直接移动头部标识 |
| 84 | + } else { |
| 85 | + changedSize -= countFirst; |
| 86 | + for (int i = doubleIndex; i < changedSize; i++) { |
| 87 | + changed[i] = changed[i + countFirst]; |
| 88 | + } |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | + return returnArray; |
| 93 | +} |
| 94 | + |
| 95 | +void test(const char *expect, const char *charged) { |
| 96 | + arrayEntry *e = arrayParse1D(charged, ARRAY_INT); |
| 97 | + |
| 98 | + int returnSize; |
| 99 | + int *returnArray = findOriginalArray(arrayValue(e), arraySize(e), &returnSize); |
| 100 | + |
| 101 | + EXPECT_EQ_STRING_AND_FREE_ACTUAL(expect, arrayToString1D(returnArray, returnSize, ARRAY_INT)); |
| 102 | + |
| 103 | + arrayFree(e); |
| 104 | +} |
| 105 | + |
| 106 | +int main(void) { |
| 107 | + test("[1,3,4]", "[1,3,4,2,6,8]"); |
| 108 | + test("[]", "[6,3,0,1]"); |
| 109 | + test("[]", "[1]"); |
| 110 | + |
| 111 | + test("[]", "[4,4]"); |
| 112 | + test("[0,2]", "[0,4,2,0]"); |
| 113 | + |
| 114 | + test("[0,0]", "[0,0,0,0]"); |
| 115 | + test("[1,2,2,3,4,6]", "[1,2,3,2,4,6,2,4,6,4,8,12]"); |
| 116 | + test("[]", "[1,4,2,1]"); |
| 117 | + |
| 118 | + return testOutput(); |
| 119 | +} |
0 commit comments