前言
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);
}
总结
- 理清思路,搭框架,如果涉及的函数较多,保证每个函数的正确性,测试用例不要立刻删除,后序做测试用。
- 单调栈,有可能栈内元素超过自己想要的元素,要注意处理
- 如果不够,要做合适的处理,将arr中的直接添加到单调栈最后(AddToEnd)
- 可以直接返回单调栈+数量,用多少取多少
- 不要犯低级错误,涉及多个索引时,不要用混!!!
- 如果循环中还需要不断向后判断,使用offset做辅助,或者单开一个函数,将当前索引传入,然后在新的函数中可以随意处理索引,而不用考虑恢复现场。