力扣练习第七天 :454.四数相加||、383.赎金信、15.三数之和、18.四数之和

  • 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才是最好的
      • 三数相加可能越界的问题要考虑到
      • 
        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语言解了出来。加油 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值