day19三数之和 int *returnSize,int ** returnColumnSizes的理解

题目描述
在这里插入图片描述
*1.关于参数 int returnSize, int ** returnColumnSizes的理解
具体看这篇文章
[https://blog.csdn.net/m0_52775920/article/details/121461911?spm=1001.2014.3001.5502]
(1)*returnSize 的理解
returnSize 返回大小为returnSize的二维数组,可以理解为returnSize就是一个指针,*returnSize就代表返回大小了,这里的大小就是我们要返回的二维数组的行数,比如上面图就是
(2)**returnColumnSizes的理解
*returnColumnSizes 是用来装我们返回的二维数组每一行有多少个元素的(即列数),如果返回 5 行,则 *returnColumnSizes 的长度也得是 5 , 比如说第一个元素是 3 表示二维数组的第一行有 3 个数,第二个元素是 4 表示二维数组的第二行有 4 个数。别人怎么知道你的二维数组有多少行?自然也就不知道应该初始化 *returnColumnSizes 数组为多大了,这一切还得你来。你 malloc 一个数组,自然就会得到一个指向数组的一阶指针,

2.题目分析
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。利用双指针,a=nums[i] ,b= nums[left],c=nums[right]; 题目要求去重,即对abc去重;

# define MAX 100000	// 答案的个数,当然也能用动态扩容
int comp(const void *a, const void *b)
{
    return *(int *)a > *(int *)b ? 1 : 0;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    qsort(nums, numsSize, sizeof(int), comp);
    int **ans = (int **)malloc(sizeof(int *) * MAX);
    *returnSize = 0;
    if (numsSize < 3)   return ans;
    int i = 0;
    while (i < numsSize - 2) {
        int left = i + 1, right = numsSize - 1;
        while (left < right) {
            int sum = nums[left] + nums[right] + nums[i];
            if (sum == 0) {
                int *temp = (int *)malloc(sizeof(int) * 3);
                temp[0] = nums[i];
                temp[1] = nums[left];
                temp[2] = nums[right];
                ans[(*returnSize)++] = temp;
            }
            // 这个地方不能是else if,因为总得改变当前的状态,如果是else if,那么找到了一个答案之后就永远不变了,这是不行的
            if (sum < 0)
                // 小了,就改变left。跳过重复的同时避免出界
                while (left < numsSize - 1 && nums[left] == nums[++left]);
            else
                // right跳过重复的
                while (right > 0 && nums[right] == nums[--right]);
        }
        // 第一个数字i,同样避免重复和越界
        while(i < numsSize - 1 && nums[i] == nums[++i]);
    }
    *returnColumnSizes = (int *)malloc(sizeof(int) * (*returnSize));
    for (int i = 0; i < (*returnSize); i++)
        (*returnColumnSizes)[i] = 3;
    return ans;
}

解法二:
1、判断输入数组为空、或元素个数小于3个,直接返回NULL
2、将输入数组升序排序
3、依次遍历排序后的数组
3.1、判断当前元素是否为正,是则结束循环,因为后续的数字也都为正,不会出现三数之和为0的情况
3.2、判断当前元素是否与上一次相等,相等则跳过进行去重
3.3、从 i + 1 到 numsSize - 1 进行左右指针判断三数之和sum:
3.3.1、sum == 0 :
1、找到一组值,进行保存
2、对left、right进行去重
3.3.2、sum < 0 :
left++
3.3.3、sum > 0
right–

int cmp(const void* a, const void* b) {
    return *(int*)a - *(int*)b;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
    /* 先记录返回的行数为0 */
    *returnSize = 0;
    /* 输入为空、或元素个数小于3则返回NULL */
    if (nums == NULL || numsSize < 3) {
        return NULL;
    }
    /* 将nums排序为升序排列 */
    qsort(nums, numsSize, sizeof(int), cmp);
    /* 分配返回数组、返回数组的列数 */
    int** ret = (int**)malloc(numsSize * numsSize * sizeof(int*));
    *returnColumnSizes = (int*)malloc(numsSize * numsSize *sizeof(int));
    /* 排序后的数组从头到尾进行遍历 */
    for (int i = 0; i < numsSize; i++) {
        /* 当前数组大于0,表示后续没有三数之和为0,结束遍历 */
        if (nums[i] > 0) {
            break;
        }
        /* 当前元素与上一次相等,跳过此次计算,去重 */
        if (i > 0 && nums[i] == nums[i - 1]) {
            continue;
        }
        /* 定义左右指针 */
        int left = i + 1, right = numsSize - 1;
        /* 开始查找三数之和为0 */
        while (left < right) {
            int sum = nums[i] + nums[left] + nums[right];
            if (sum == 0) {
                ret[*returnSize] = (int*)malloc(sizeof(int) * 3);
                ret[*returnSize][0] = nums[i];
                ret[*returnSize][1] = nums[left];
                ret[*returnSize][2] = nums[right];
                /* 返回数组当前行的列数为3 */
                (*returnColumnSizes)[*returnSize] = 3;
                /* 返回数组的行数自加1 */
                (*returnSize)++;
                /* 对左右指针进行去重 */
                while (left < right && nums[left]  == nums[++left]);
                while (left < right && nums[right] == nums[--right]);
            } else if (sum < 0) {
                left++;
            } else {
                right--;
            }
        }
    }
    return ret;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现阳历转农历的代码需要用到农历的一些计算方法,以下是一个实现的例子: ```c // 公历转农历 void solarToLunar(int year, int month, int day, int *lunarYear, int *lunarMonth, int *lunarDay) { // 农历数据表 int lunarInfo[] = { 0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8, 0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0, 0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0, 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0 }; int leapMonth = 0; // 闰月 int daysOfYear = 0; // 公历当年天数 int daysOfMonth = 0; // 公历当月天数 int daysOfLunarYear = 0; // 农历当年天数 int daysOfLunarMonth = 0; // 农历当月天数 int lunarYearDays = 0; // 当年闰月天数 int i, j; // 计算公历当年天数 for (i = 1; i <= month - 1; i++) { daysOfYear += solarMonthDays(year, i); } daysOfYear += day; // 计算农历当年闰月 leapMonth = lunarInfo[year - 1900] & 0xf; // 计算农历当年天数 daysOfLunarYear = 0; for (i = 1; i <= 12; i++) { daysOfLunarMonth = (lunarInfo[year - 1900] & (0x10000 >> i)) ? 30 : 29; if (leapMonth == i) { // 闰月 lunarYearDays += daysOfLunarMonth; continue; } daysOfLunarYear += daysOfLunarMonth; } lunarYearDays += leapMonth ? (daysOfLunarYear + 29) : daysOfLunarYear; // 计算农历当年的天数差 daysOfYear -= lunarYearDays; // 计算农历月份和日子 for (i = 1; i <= 12; i++) { daysOfLunarMonth = (lunarInfo[year - 1900] & (0x10000 >> i)) ? 30 : 29; if (leapMonth == i) { // 闰月 lunarYearDays = daysOfLunarMonth + 29; } else { lunarYearDays = daysOfLunarMonth; } if (daysOfYear <= lunarYearDays) { *lunarMonth = i; *lunarDay = daysOfYear; break; } daysOfYear -= lunarYearDays; } *lunarYear = year; } ``` 在该函数中,我们通过计算公历当年的天数和农历当年的天数,以及农历当年的闰月天数,来计算出农历的月份和日子。需要注意的是,该函数中用到了一个`solarMonthDays`函数,用于计算公历当月的天数,需要自行实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值