算法笔记-两数之和、三数之和、四数之和(LeetCode)

青旅半醒 2023-02-14 02:29 129阅读 0赞

两数之和

1.两数之和
题目:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

  1. 给定 nums = [2, 7, 11, 15], target = 9
  2. 因为 nums[0] + nums[1] = 2 + 7 = 9
  3. 所以返回 [0, 1]

代码:

  1. /**
  2. * Note: The returned array must be malloced, assume caller calls free().
  3. */
  4. int* twoSum(int* nums, int numsSize, int target, int* returnSize){
  5. if(nums==NULL) return NULL;
  6. int *res = (int*)malloc(sizeof(int)*2);
  7. *returnSize = 2;
  8. for(int i= 0;i<numsSize;i++) {
  9. for(int j = i+1;j<numsSize;j++) {
  10. if(nums[i] + nums[j] == target) {
  11. res[0] = i;
  12. res[1] = j;
  13. break;
  14. }
  15. }
  16. }
  17. return res;
  18. }

167.两数之和II-输入有序数组
题目:给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

示例:

  1. 输入: numbers = [2, 7, 11, 15], target = 9
  2. 输出: [1,2]
  3. 解释: 2 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2
  4. int* twoSum(int* numbers, int numbersSize, int target, int* returnSize){
  5. if(numbers==NULL) return NULL;
  6. int *res = (int*)malloc(sizeof(int)*2);
  7. *returnSize = 2;
  8. for(int i= 0;i<numbersSize-1;i++) {
  9. for(int j = i+1;j<numbersSize;j++) {
  10. if(numbers[i] + numbers[j] == target) {
  11. res[0] = i+1;
  12. res[1] = j+1;
  13. break;
  14. }
  15. }
  16. }
  17. return res;
  18. }

对上述两个题目的总结:
题目区别:返回的下标是否从0开始
代码区别:
1

  1. res[0] = i;
  2. res[1] = j;

167

  1. res[0] = i+1;
  2. res[1] = j+1;

三数之和

15.三数之和
题目:给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

  1. 给定数组 nums = [-1, 0, 1, 2, -1, -4],
  2. 满足要求的三元组集合为:
  3. [
  4. [-1, 0, 1],
  5. [-1, -1, 2]
  6. ]

代码:

  1. //先将数组进行排序,然后进行三重循环。其中,前两重循环,使用普通遍历即可,需要做一下剪枝。
  2. //第三重循环,我这里用了二分查找(不用,或许也行),可以优化一下速度
  3. int cmp(const void *a, const void *b)
  4. {
  5. return *(int*)a - *(int*)b; // 比较大小
  6. }
  7. /**
  8. * Return an array of arrays of size *returnSize.
  9. * The sizes of the arrays are returned as *returnColumnSizes array.
  10. * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
  11. */
  12. int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
  13. {
  14. if (nums == NULL || returnSize == NULL || returnColumnSizes == NULL) {
  15. return NULL;
  16. }
  17. // 方便起见,先申请足够的内存
  18. int max_count = numsSize * numsSize; // 认为足够了
  19. int **p = (int **)malloc(sizeof(int*) * max_count);
  20. if (p == NULL) {
  21. // 申请内存是否失败
  22. return NULL;
  23. }
  24. *returnColumnSizes = (int*)malloc(sizeof(int) * max_count);
  25. if (*returnColumnSizes == NULL) {
  26. // 申请内存是否失败
  27. free(p); // 释放之前申请的内存
  28. return NULL;
  29. }
  30. memset(*returnColumnSizes, 0, sizeof(int) * max_count);
  31. *returnSize = 0;
  32. // 从小到大排序,时间复杂度O(nlogn)
  33. qsort(nums, numsSize, sizeof(int), cmp);
  34. /* for (int i = 0; i < numsSize; i++) {
  35. printf("%d, ", nums[i]);
  36. }
  37. printf("\n"); */
  38. for (int i = 0; i < numsSize; i++) {
  39. if (nums[i] > 0) {
  40. // 剪枝
  41. continue;
  42. }
  43. if (i > 0 && nums[i] == nums[i - 1]) {
  44. // 剪枝
  45. continue;
  46. }
  47. for (int j = i + 1; j < numsSize; j++) {
  48. if (nums[i] + nums[j] > 0) {
  49. // 剪枝
  50. continue;
  51. }
  52. if (j > i + 1 && nums[j] == nums[j - 1]) {
  53. // 剪枝
  54. continue;
  55. }
  56. // 这里用二分查找,进行优化
  57. int left = j + 1;
  58. int right = numsSize - 1;
  59. while (left <= right) {
  60. int mid = (left + right) / 2;
  61. int sum = nums[i] + nums[j] + nums[mid];
  62. // printf("[%d]%d + [%d]%d + [%d]%d = (%d-%d)%d\n",
  63. // i, nums[i], j, nums[j], mid, nums[mid], left, right, sum);
  64. if (sum == 0) {
  65. // 找到一个解
  66. p[*returnSize] = (int*)malloc(sizeof(int) * 3);
  67. if (p[*returnSize] == NULL) {
  68. return NULL;
  69. }
  70. p[*returnSize][0] = nums[i];
  71. p[*returnSize][1] = nums[j];
  72. p[*returnSize][2] = nums[mid];
  73. (*returnColumnSizes)[*returnSize] = 3;
  74. (*returnSize)++;
  75. break; // 找到则退出
  76. } else if (sum > 0) {
  77. right = mid - 1;
  78. } else {
  79. left = mid + 1;
  80. }
  81. }
  82. }
  83. }
  84. return p;
  85. }

疑惑:不清楚下面这样子为什么不可以
此处附上错误代码:

  1. /**
  2. * Return an array of arrays of size *returnSize.
  3. * The sizes of the arrays are returned as *returnColumnSizes array.
  4. * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
  5. */
  6. int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
  7. if(nums==NULL)
  8. return NULL;
  9. int *res = (int*)malloc(3*sizeof(int));
  10. *returnSize = 3;
  11. int i,j,k;
  12. for(i=0; i<numsSize-2; i++)
  13. {
  14. for(j=i+1; j<numsSize-1; j++)
  15. {
  16. for(k=j+1; k<numsSize; k++)
  17. {
  18. if(nums[i]+nums[j]+nums[k]==0)
  19. {
  20. res[0]=i;
  21. res[1]=j;
  22. res[2]=k;
  23. break;
  24. }
  25. }
  26. }
  27. }
  28. return res;
  29. }

在这里插入图片描述
搜索了一下错误的原因:

  • LeetCode使用了AddressSanitizer检查了是否存在内存非法访问。
  • 在该题目中,是因为数组访问越界,也是绝大部分的内存访问题。

可是我不觉得自己for循环里有问题啊,如果大佬看到了错误或者有思路,愿闻详解,本菜鸟的荣幸

四数之和

18.四数之和
题目:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:
答案中不可以包含重复的四元组。

示例:

  1. 给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0
  2. 满足要求的四元组集合为:
  3. [
  4. [-1, 0, 0, 1],
  5. [-2, -1, 1, 2],
  6. [-2, 0, 0, 2]
  7. ]

发表评论

表情:
评论列表 (有 0 条评论,129人围观)

还没有评论,来说两句吧...

相关阅读

    相关 leetcode1. js

    给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应

    相关 LeetCode

    给定一个整数数组 `nums` 和一个目标值 `target`,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是