- 454.四数相加||
- 哈哈,开心,用c语言自己做出来了。美的飞起。
- 首先,看了卡哥的提示,要用map解题。key用来存储nums1[i]+nums2[j的和, value用来存储出现的次数。
- 另外 ,还有个小小的问题, 就是if(s)(光标所在处)中重新分配一次,就会报错,这是为什么呢?是重新弄了一块内存吗?但是现在找到的不是指针吗???这是一个小疑问,与昨天的一些想法有了冲突。
- 下附正确的代码
struct HashTable { int key; int value; UT_hash_handle hh; }; int fourSumCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* nums3, int nums3Size, int* nums4, int nums4Size){ int count = 0; struct HashTable* hash = NULL; for (int i = 0; i < nums1Size; i++) { for (int j = 0; j < nums2Size; j++) { struct HashTable* s = NULL; int num = nums1[i] + nums2[j]; HASH_FIND_INT(hash, &num, s); if (s) { s->value++; } else { s = (struct HashTable*)malloc(sizeof(struct HashTable)); s->key = nums1[i] + nums2[j]; s->value = 1; HASH_ADD_INT(hash, key, s); } } } for (int i = 0; i < nums3Size; i++) { for (int j = 0; j < nums3Size; j++) { int num = -(nums3[i] + nums4[j]); struct HashTable* s = NULL; HASH_FIND_INT(hash, &num, s); if (s) { count += s->value; } } } return count; }
- 383.赎金信
- 非常简单了 但是我还是错了一些
- 首先没有看清题意,谁是谁的子集
- 其实,我居然把数组设置到了10001,牛! 还有就是判断 == 误写成了 =;
- 附上代码
bool canConstruct(char * ransomNote, char * magazine){ int result[26] = {0}; int lenR = strlen(ransomNote); int lenM = strlen(magazine); for (int i = 0; i < lenM; i++) { result[magazine[i] - 'a']++; } for (int i = 0; i < lenR; i++) { if (result[ransomNote[i] - 'a'] == 0) return false; else result[ransomNote[i] - 'a']--; } return true; }
- 附上代码
- 15.三数之和
- 卡哥提要说 哈希表很麻烦 。盲猜是因为答案中不可以包含重复的三元组,这在上面的四数之和||中没有要求的。确实,用了哈希,怎么判断,有没有加入相同的东西呢???
- 双指针
- 失败:
- 又一次忘记了二维数组的创建和返回。
-
int** ans = (int**)malloc(sizeof(int*) * 20000); int* arr = (int*)malloc(sizeof(int) * 3); arr[0] = nums[i]; arr[1] = nums[slow]; arr[2] = nums[fast]; ans[top++] = arr; *returnSize = top; *returnColumnSizes = malloc(sizeof(int) * top); for (int i = 0; i < top; i++) { (*returnColumnSizes)[i] = 3; }
- 忘记了剪枝的操作
- 很有技巧: 什么时候剪枝?为什么要剪枝
- 1. 第一个for循环里 :我们要求三个数和为0 , 那么当第一个数就已经大于0 了,此时绝对不可能有三数之和等于0 所以此时break结束循环。
- 还有就是当我们发现 此时的nums【i】和nums[i - 1]相等的时候 是要continue跳过这个数
- 忘记了三个数直接相加可能会越界的问题。。。
- 为什么剪枝,第一个就是减少了很多判断。第二个就是防止重复加入。
- 在forwhileif中,找到了某一组值,接下来就要剪枝,看看left右边一个是不是和自己相等,righ左边一个是不是和自己相等,还要注意我们这里不能用if而是while来执行,循环判断剪枝。
- 我这里双指针用成了slow和fast有些不妥,用left和right才是最好的
- 1. 第一个for循环里 :我们要求三个数和为0 , 那么当第一个数就已经大于0 了,此时绝对不可能有三数之和等于0 所以此时break结束循环。
- 很有技巧: 什么时候剪枝?为什么要剪枝
- 三数相加可能越界的问题要考虑到
-
int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; } int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){ qsort(nums, numsSize, sizeof(int), cmp); int sum = -1; int top = 0; int** ans = (int**)malloc(sizeof(int*) * 20000); if (numsSize < 3) { *returnSize = 0; return ans; } for (int i = 0; i < numsSize - 2; i++) { if (nums[i] > 0) break; if (i > 0 && nums[i] == nums[i - 1]) continue; int slow = i + 1; int fast = numsSize - 1; while (slow < fast) { if (nums[i] == - nums[slow] - nums[fast]) { int* arr = (int*)malloc(sizeof(int) * 3); arr[0] = nums[i]; arr[1] = nums[slow]; arr[2] = nums[fast]; ans[top++] = arr; while(slow < fast && nums[slow] == nums[slow + 1]) { slow++; } while(slow < fast && nums[fast] == nums[fast - 1]) { fast--; } slow++; fast--; } else if (nums[i] > - nums[slow] - nums[fast]) fast--; else if (nums[i] < - nums[slow] - nums[fast]) slow++; } } *returnSize = top; *returnColumnSizes = malloc(sizeof(int) * top); for (int i = 0; i < top; i++) { (*returnColumnSizes)[i] = 3; } return ans; }
- 18.四数之和
- wolegequ
- 或许你以为这和三数之和没什么差别?
- 太多太多太多需要注意的地方了
-
if (nums[i] > target && target > 0)
- 上面这句话target > 0 (或者 nums[i] > 0) 你读懂了吗?
- 道理其实很简单,如果target是一个负数, 那么需要好几个负数叠加在一块,才能构成一个更小的target 所以我们加上了nums[i] > 0 用来判断一下target不是负数
-
if (i > 0 && nums[i] == nums[i - 1]) if (j > i + 1 && nums[j] == nums[j - 1])
- 如何避免出现两组相同的东西,上面这俩就告诉你答案了。看好 i > 0 , 这是要告诉你第一个数我是不操作的,就算你想操作,那系统就报错哈。那j > i + 1 呢? 也是为了重复,但是这里没有大于也可能出现错误,并且系统是不会报错,因为你j - 1此时是有效的,而i-1是无效的东西。
- 还有,依然是越界的问题,可能你还是想按照三数之和的套路来,但是我要告诉你,这不行了……你必须这样搞
if ((long)nums[i] + nums[j]+nums[left]+nums[right]<target)
- 看起来很相同,但是实际操作起来二者还是有很大的差别的。就前两个东西来看,如果不看解析,很难想到的。
- 附上我的code
int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; } int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes){ qsort(nums, numsSize, sizeof(int),cmp); int** ans = (int**)malloc(sizeof(int*) * 18000); int ansTop = 0; if (numsSize < 4) { *returnSize = 0; return ans; } for (int i = 0; i < numsSize - 3; i++) { if (nums[i] > target && target > 0) break; if (i > 0 && nums[i] == nums[i - 1]) continue; for (int j = i + 1; j < numsSize - 2; j++) { if (nums[i] + nums[j] > target && target > 0) break; if (j > i + 1 && nums[j] == nums[j - 1]) continue; int left = j + 1; int right = numsSize - 1; while (left < right) { if ((long)nums[i] + nums[j]+nums[left]+nums[right]<target){ left++; } else if((long)nums[i] +nums[j]+nums[left]+nums[right]>target){ right--; } else { int* arr = (int*)malloc(sizeof(int) * 4); arr[0] = nums[i]; arr[1] = nums[j]; arr[2] = nums[left]; arr[3] = nums[right]; ans[ansTop++] = arr; while (left < right && nums[left] == nums[left+1]) left++; while (left < right && nums[right] == nums[right - 1]) right--; left++; right--; } } } } *returnSize = ansTop; *returnColumnSizes = (int*)malloc(sizeof(int)* ansTop); for (int i = 0; i < ansTop; i++) { (*returnColumnSizes)[i] = 4; } return ans; }
今天刷了两个半小时左右,总体感觉不错。毕竟第一题靠c语言解了出来。加油