【LeetCode】【C】321. 拼接最大数时--隔两个月两次刷的代码

前言

LeetCode做题的数量多不如质量高,在基本算法都掌握的基础上,关键是能够掌握寻找答案的思路以及以及一些细节上的技巧性处理。
通过两次刷这道题,最后对比代码可以发现,在方向对的前提下,两次的编码细节是不同的,有些地方用了不同的处理思想,第一次解答这个题是看了答案之后做的,有些地方潜移默化用了答案里的技巧,当时没有察觉,当自己再次刷题时,有可能会出现一些自己的土方法,通过对比,才能将更好的方法吸收。

题目链接

拼接最大数

话不多说,上代码

第一次(查看答案后的编码)

static inline int MAX(int x, int y) 
{
    return x > y ? x : y;
}
static inline int MIN(int x, int y) 
{
    return x < y ? x : y;
}

void AddToEnd(int *relt, int head, int *nums, int numsSize, int pos) 
{
    for (int j = pos; j < numsSize; j++){
        relt[++head] = nums[j];
    }
}
int *SelNum(int *nums, int numsSize, int n)
{
    if (n == 0) {
        return NULL;
    }
    int *relt = (int *)malloc(sizeof(int) * numsSize);
    memset(relt, 0, sizeof(int) * numsSize);
    int head = -1;
    relt[++head] = nums[0];
    int i;
    for (i = 1; i < numsSize; i++) {
        if (numsSize - i + head + 1 == n) {
            // printf("%d", head);
            AddToEnd(relt, head, nums, numsSize, i);    // 将剩余的数字全部放入单调栈内
            break;
        }
        while (head >= 0 && nums[i] > relt[head] && numsSize - i + head + 1 > n) {
            head--;
        }
        relt[++head] = nums[i];
    }
    return relt;        // 选择直接使用单调栈返回
}
int ChoseOne(int *s1, int idx1, int s1Len, int *s2, int idx2, int s2Len)
{
    while(idx1 < s1Len && idx2 < s2Len && s1[idx1] == s2[idx2]) {
        idx1++;
        idx2++;
    }
    if (idx1 == s1Len && idx2 == s2Len) {
        return 1;
    } else if (idx1 == s1Len){
        if (s2[idx2] >= s1[idx1 - 1]) {
            return 0;
        } else {
            return 1;
        }
    } else if (idx2 == s2Len){
        if (s1[idx1] >= s2[idx2 - 1]) {
            return 1;
        } else {
            return 0;
        }
    } else if (s2[idx2] > s1[idx1]) {
        return 0;
    } 
    return 1;
}
int* UpdateMax(int *relt, int *s1, int s1Len, int *s2, int s2Len)
{
    int idx1 = 0;
    int idx2 = 0;
    int idx = 0;
    int reltLen = s1Len + s2Len;
    int *reltTmp = (int *)malloc(sizeof(int) * reltLen);
    memset(reltTmp, 0, sizeof(int) * reltLen);
    while (idx1 < s1Len && idx2 < s2Len) {
        if (s1[idx1] > s2[idx2]) {
            reltTmp[idx++] = s1[idx1++];
        } else if (s1[idx1] < s2[idx2]){
            reltTmp[idx++] = s2[idx2++];
        } else {
            reltTmp[idx++] = (ChoseOne(s1, idx1, s1Len, s2, idx2, s2Len)) ? s1[idx1++] : s2[idx2++];
        }
    }
    while (idx1 < s1Len) {
        reltTmp[idx++] = s1[idx1++];
    }
    while (idx2 < s2Len) {
        reltTmp[idx++] = s2[idx2++];
    }
    for (int i = 0; i < reltLen; i++) {
        if (relt[i] > reltTmp[i]) {
            free(reltTmp);
            return relt;
        } else if (relt[i] < reltTmp[i]) {
            free(relt);
            return reltTmp;
        }
    }

    free(relt);
    return reltTmp;
} 
int* maxNumber(int* nums1, int nums1Size, int* nums2, int nums2Size, int k, int* returnSize){
    int  *relt = (int *)malloc(sizeof(int) * k);
    memset(relt, 0, sizeof(int) * k);
    int s1Len = 0;
    int s2Len;
    int *s1, *s2;
    int aimLen = MIN(nums1Size, k);
    while (s1Len <= aimLen) {
        s2Len = k - s1Len;
        if (k - s1Len > nums2Size) {
            s1Len++;
            continue;
        }
        s1 = SelNum(nums1, nums1Size, s1Len);
        s2 = SelNum(nums2, nums2Size, s2Len);

        relt = UpdateMax(relt, s1, s1Len, s2, s2Len);
        s1Len++;
    }
    
    *returnSize = k;
    return relt;
}

二刷

int *NumUpdate(int *orig, int *new, int k){
    for (int i = 0; i < k; i++) {
        if (new[i] > orig[i]) {
            free(orig);
            return new;
        } else if (new[i] < orig[i]){
            free(new);
            return orig;
        }
    }
    free(new);
    return orig;
}
int *NumSelect(int *arr, int arrLen, int n) {
    int sgSt[arrLen];
    int head = -1;
    int i;
    if (n == 0) {
        return NULL;
    }
    for (i = 0; i < arrLen; i++)
    {
        // 此处等于需要仔细考虑
        while(head  >= 0 && arr[sgSt[head]] < arr[i] && 
              (head + 1 + arrLen - i - 1) >= n) {
            head--;
        }
        sgSt[++head] = i;
        if (head + 1 + arrLen - i - 1 == n) {
            i++;
            break;
        }
    }
    int *relt = (int *)malloc(sizeof(int) * n);
    int idx = 0;
    if (head + 1 >= n) {    // 栈内元素足够
        for (int m = 0; m < n; m++) {
            relt[idx++] = arr[sgSt[m]];
        }         
    } else {
        for (int m = 0; m <= head; m++) {
            relt[idx++] = arr[sgSt[m]];
        }
        
        while (i < arrLen) {
            relt[idx++] = arr[i++];
        }
    }

    return relt;
}
int *NumCompose(int *arr1, int arrLen1, int *arr2, int arrLen2) {
    int arrPt1 = 0;
    int arrPt2 = 0;
    int *relt = (int *)malloc(sizeof(int) * (arrLen1 + arrLen2));
    int idx = 0;
    while (arrPt1 < arrLen1 && arrPt2 < arrLen2)
    {
        if (arr1[arrPt1] > arr2[arrPt2]) {
            relt[idx++] = arr1[arrPt1++];
        } else if (arr1[arrPt1] < arr2[arrPt2]) {
            relt[idx++] = arr2[arrPt2++];
        } else {
            int offset=0;
            while (arrPt1 + offset < arrLen1 && arrPt2 + offset < arrLen2) {
                if (arr1[arrPt1 + offset] > arr2[arrPt1 + offset]) {
                    relt[idx++] = arr1[arrPt1++];
                    break;
                }
                else if (arr1[arrPt1 + offset] < arr2[arrPt2 + offset])
                {
                    relt[idx++] = arr2[arrPt2++];
                    break;
                }
                else
                {
                    offset++;
                    if (arrPt1 + offset == arrLen1) {
                        relt[idx++] = arr2[arrPt2++];
                    } else if (arrPt2 + offset == arrLen2) {
                        relt[idx++] = arr1[arrPt1++];
                    }
                }
            }
        }
    }
    while (arrPt1 < arrLen1){
        relt[idx++] = arr1[arrPt1++];
    }
    while (arrPt2 < arrLen2) {
        relt[idx++] = arr2[arrPt2++];
    }
    return relt;
}

int* maxNumber_(int* nums1, int nums1Size, int* nums2, int nums2Size, int k, int* returnSize){
    int *reltTmp = malloc(sizeof(int) * k);
    memset(reltTmp, 0, sizeof(int) * k);
    int *buf1;
    int *buf2;
    int maxCnt = nums1Size > k ? k : nums1Size;
    for (int i = 0; i <= maxCnt; i++)
    {   
        if (k-i > nums2Size) {
            continue;
        }
        buf1 = NumSelect(nums1, nums1Size, i);
        buf2 = NumSelect(nums2, nums2Size, k - i);
        int *curRelt = NumCompose(buf1, i, buf2, k - i);
        ArrPrint(curRelt, k, "current i is %d", i);
        reltTmp = NumUpdate(curRelt, reltTmp, k);
    }

    *returnSize = k;
    return reltTmp;
}
int* maxNumber_2(int* nums1, int nums1Size, int* nums2, int nums2Size, int k, int* returnSize){
    int *relt;
    if (nums1Size > nums2Size)
    {
        return maxNumber_(nums2, nums2Size, nums1, nums1Size, k, returnSize);
    }
    return maxNumber_(nums1, nums1Size, nums2, nums2Size, k, returnSize);
}

总结

  1. 理清思路,搭框架,如果涉及的函数较多,保证每个函数的正确性,测试用例不要立刻删除,后序做测试用。
  2. 单调栈,有可能栈内元素超过自己想要的元素,要注意处理
    • 如果不够,要做合适的处理,将arr中的直接添加到单调栈最后(AddToEnd)
    • 可以直接返回单调栈+数量,用多少取多少
  3. 不要犯低级错误,涉及多个索引时,不要用混!!!
  4. 如果循环中还需要不断向后判断,使用offset做辅助,或者单开一个函数,将当前索引传入,然后在新的函数中可以随意处理索引,而不用考虑恢复现场。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值