Leetcode——4Sum(load of null pointer of type int *(_Seriakizer_.c)异常原因和处理方法) **returnColumnSize到底是啥

题目描述

Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

现给一个n个整数的整型数组和一个整型的目标数,在整型数组中是否存在着的这样的四个数a,b,c,d,四者相加为整型目标数?在数组中,找到所有的和为整型目标数的不同的组

Note:

The solution set must not contain duplicate quadruplets.

结果的集合种的不可以包含重复的组合

Example:

Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.

A solution set is:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

方法一、BruteForce

思路分析
* 主要是模仿3Sum的解决办法
  * 先对的整个数列进行排序的,同时确定a,b,c和d的的相对位置,减少重复元素的出现
  * 再者,用两重循环,最外层的循环确定的a的值,第二层循环确定的b的值,然后第二层循环的内部采用解决2sum的two pinter方法
  * 何为two pinter方法:
      * 确定两个边left和right,left + eright = target,left和right分别从数组的左右两端开始的遍历,left从左往右,即从小往大开始遍历。right从右往左开始遍历,即从大往小。根据left + right的值和target的关系进行判定
      * 如果left + right > target,说明需要变小,那就移动right
      * 如果left + right <target,说明需要变大,那就移动left


##### C语言实现

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
 void bubble(int *nums , int numSize)
 {
    
    
     int temp;
     for(int i = 0;i < numSize - 1;i ++)
     {
    
    
         for(int j = i + 1;j < numSize;j ++)
         {
    
    
             if(nums[i] > nums[j])
             {
    
    
                 temp = nums[i];
                 nums[i] = nums[j];
                 nums[j] = temp;
             }
         }
     }
 }


int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes)
{
    
    
    int **result ;
    result = malloc(sizeof(int*)*1);
    (*returnColumnSizes) = malloc(sizeof(int)*1);
    if(nums == NULL || numsSize <= 0)
    {
    
    
        *returnSize = 0;
        *returnColumnSizes = NULL;
        return NULL;
    }
    bubble(nums,numsSize);
    int left = 0,right = 0 ;
    *returnSize = 0;
    for(int i = 0; i < numsSize ; i ++) {
    
    
        for(int j = i + 1; j < numsSize; j ++) {
    
    
            left = j + 1,right = numsSize - 1;
            while(left < right) {
    
    
                if(nums[left] + nums[right] == target - nums[i] - nums[j]) {
    
    
                    result[*returnSize] = malloc(sizeof(int) * 4);
                    result[*returnSize][0] = nums[i];
                    result[*returnSize][1] = nums[j];
                    result[*returnSize][2] = nums[left];
                    result[*returnSize][3] = nums[right];
                    (*returnColumnSizes)[*returnSize] = 4;
                    (*returnSize) ++;

                    //这里的申请函数好像并没有任何的作用
                    result = realloc(result,sizeof(int*)*(*returnSize + 1));
                    (*returnColumnSizes)=realloc(*returnColumnSizes,sizeof(int)*(*returnSize+1));
                    do
                    {
    
    
                        left++;
                    }while(left < numsSize && nums[left] == nums[left - 1]);
                } else if(nums[left] + nums[right] < target - nums[i] - nums[j]) {
    
    
                    left ++;
                } else {
    
    
                    right --;
                }
            }
            while(j + 1 < numsSize && nums[j] == nums[j + 1])
            {
    
    
                j ++;
            }
        }
        while(i + 1 < numsSize && nums[i] == nums[i + 1])
        {
    
    
            i ++;
        }
    }
    return result;
}

在这里插入图片描述

完整的测试代码
#include <stdio.h>
#include <stdlib.h>
int** fourSum(int *nums, int numSize,int target,int *returnSize,int **returnColumnSizes);
void bubble(int nums[],int numSize);

int main()
{
    
    
    int nums[] = {
    
    -497,-494,-484,-477,-453,-453,-444,-442,-428,-420,-401,-393,-392,-381,-357,-357,-327,-323,-306,-285,-284,-263,-262,-254,-243,-234,-208,-170,-166,-162,-158,-136,-133,-130,-119,-114,-101,-100,-86,-66,-65,-6,1,3,4,11,69,77,78,107,108,108,121,123,136,137,151,153,155,166,170,175,179,211,230,251,255,266,288,306,308,310,314,321,322,331,333,334,347,349,356,357,360,361,361,367,375,378,387,387,408,414,421,435,439,440,441,470,492};
    int numSize = 99;
    int target = 1682;
    int returnSize = 0;
    int *returnColumnSize =NULL;
    int **result = fourSum(nums,numSize,target,&returnSize,&returnColumnSize);
    printf("---------------------------------------------\n");
    for(int i = 0;i < returnSize;i ++)
    {
    
    
        printf("%d   ",returnColumnSize[i]);
    }

    printf("\n");
    for(int i = 0;i < returnSize;i ++)
    {
    
    
        for(int j = 0;j < 4;j ++)
        {
    
    
            printf("%d    ",*(*(result+i)+j));
        }
        printf("\n");
    }
    printf("Hello world!\n");

    return 0;
}



/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */

 void bubble(int *nums , int numSize)
 {
    
    
     int temp;
     for(int i = 0;i < numSize - 1;i ++)
     {
    
    
         for(int j = i + 1;j < numSize;j ++)
         {
    
    
             if(nums[i] > nums[j])
             {
    
    
                 temp = nums[i];
                 nums[i] = nums[j];
                 nums[j] = temp;
             }
         }
     }
 }


int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes)
{
    
    
    int **result ;
    result = malloc(sizeof(int*)*1);
    (*returnColumnSizes) = malloc(sizeof(int)*1);
    if(nums == NULL || numsSize == 0)
    {
    
    
        *returnSize = 0;
        *returnColumnSizes = NULL;
        return NULL;
    }
    bubble(nums,numsSize);
    int left = 0,right = 0 ;
    *returnSize = 0;
    for(int i = 0; i < numsSize ; i ++) {
    
    
        for(int j = i + 1; j < numsSize; j ++) {
    
    
            left = j + 1,right = numsSize - 1;
            while(left < right) {
    
    
                printf("left:%d  \n",nums[left]);
                printf("right:%d  \n",nums[right]);
                if(nums[left] + nums[right] == target - nums[i] - nums[j]) {
    
    
                    result[*returnSize] = malloc(sizeof(int) * 4);
                    result[*returnSize][0] = nums[i];
                    result[*returnSize][1] = nums[j];
                    result[*returnSize][2] = nums[left];
                    result[*returnSize][3] = nums[right];
                    (*returnColumnSizes)[*returnSize] = 4;
                    (*returnSize) ++;

                    //这里的申请函数好像并没有任何的作用
                    result = realloc(result,sizeof(int*)*(*returnSize + 1));
                    (*returnColumnSizes)=realloc(*returnColumnSizes,sizeof(int)*(*returnSize+1));
                    do
                    {
    
    
                        left++;
                    }while(left < numsSize && nums[left] == nums[left - 1]);
                } else if(nums[left] + nums[right] < target - nums[i] - nums[j]) {
    
    
                    left ++;
                } else {
    
    
                    right --;
                }
            }
            while(j + 1 < numsSize && nums[j] == nums[j + 1])
            {
    
    
                j ++;
            }
        }
        while(i + 1 < numsSize && nums[i] == nums[i + 1])
        {
    
    
            i ++;
        }
    }
    return result;
}
分析与总结
  • C语言并没有那么多的数据结构的,很多的数据结构的都需要自己写。在本题中的,在函数中申请一个二维数组,还需要是动态的,因为并不知道随机传入的数组到底会构成几组答案。
returnColumnSize到底是啥
  • 题目中的给定的传入参数的比较迷惑,经历好一番功夫才明白并获得解答
int** fourSum(int *nums, int numSize,int target,int *returnSize,int **returnColumnSizes);

 * 因为答案是一个二维的数组
 * 行数通过整数eturnSize确定,是一个确定的整数,所以传入在main函数中声明的整型数returnSize的地址即可
 * 每一行的列数不一样,需要一个一维数组确定,但是一维数组的长度又是由行数确定,但是行数不确定,所以在main函数的传入一个空的声明过的一维数组的指针,将该指针的地址传入函数,在函数中为其声明空间
  • 关于指针的解引用和自增自减运算符优先级没有分情。本质上来说,自增自减的优先级一定高于指针的解引用。
//++在后
int *p;
*p ++;
*(p++);
//先是返回*p的值,在对指针p进行的++操作
(*p)++;
//先返回*p的值,在对*p的值进行++操作
++*p;
++(*p);
//先将的*p的值++,然后再返回加了之后的值

  • 关于指针的解引用和数组调用元素操作的优先级!
 *returnColumnSize[0] = 1;
 //注意这里写错了,先进行returnColumnSize[0]操作,在进行的解引用,这是一堆乱码
 (*returnColumnSize)[0] = 1;
 //正确的应该是这样写,本身传入的就是指针的指针
错误处理
  • 原因:函数返回的指针地址指向函数内部的地址,在函数退出的时候的,数组的存储空间会被销毁,此时再去访问这个地址就会出现错误
  • 常规处理方法:
    • 返回的指针提前分配空间
    • 用static修饰变量,使之静态存储区的变量
    • 使用全局变量
      在这里插入图片描述
  • 解决代码:即使返回的是的空数组,但是没有将的别的一些标识量进行的指定,如returnSize = 0;returnColumnSizes没有将之设置为空
 if(nums == NULL || numsSize == 0)
    {
    
    
        *returnSize = 0;
        *returnColumnSizes = NULL;
        return NULL;
    }
  • 完成这道题,经历很多的波折,光是参数的理解就花费了很多的时间,除此之外,在很多的两边法消除重复元素上也有很多的疏漏,总结出如下的几条原则
    • 凡是指针的解引用和别的符号相混杂使用的,一定要在指针的解引用上方加上括号
    • 只要涉及到数组索引的使用,一定要进行的要提前判定的,这个数组有没有越界

方法二、Recursion实现普遍问题

思路分析
  • 首先针对的这一类问题,可能会出现5sum,6sum。。。。等一系列的问题,故而关键在于如何书写一个解决这一类的问题的方法
  • 参考一下3sum是在2sum外岑提前讨一个循环,4sum无非就是在3sum外层嵌套一个循环,因此nsum就是在n-1sum外层嵌套循环,所以采用递归来处理这个问题
python代码实现
class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        def kSum(nums: List[int], target: int, k: int) -> List[List[int]]:
            res = []
            if len(nums) == 0 or nums[0] * k > target or target > nums[-1] * k:
                return res
            if k == 2:
                return twoSum(nums, target)
            for i in range(len(nums)):
                if i == 0 or nums[i - 1] != nums[i]:
                    for _, set in enumerate(kSum(nums[i + 1:], target - nums[i], k - 1)):
                        res.append([nums[i]] + set)
            return res

        def twoSum(nums: List[int], target: int) -> List[List[int]]:
            res = []
            lo, hi = 0, len(nums) - 1
            while (lo < hi):
                sum = nums[lo] + nums[hi]
                if sum < target or (lo > 0 and nums[lo] == nums[lo - 1]):
                    lo += 1
                elif sum > target or (hi < len(nums) - 1 and nums[hi] == nums[hi + 1]):
                    hi -= 1
                else:
                    res.append([nums[lo], nums[hi]])
                    lo += 1
                    hi -= 1
            return res

        nums.sort()
        return kSum(nums, target, 4)
分析与总结
  • 有很多的细微独到之处值得学习,已经将问题进行了最简化的处理,排除很多的不必要的情况。同时这样的方式由具有普遍性的,是一个质得学习的好方法

猜你喜欢

转载自blog.csdn.net/Blackoutdragon/article/details/108623764