算法打卡:力扣18 四数之和 c&&python实现

在这里插入图片描述
在这里插入图片描述先前已经做过了两数之和,三数之和,现在到了四数之和,我在想有没有一个统一的方法可以针对k数之和去做,但是目前还没有找到一个适合与一个k数之和的方法(k>=2),今天先来看这道题目:
题意明确,相信很多刷过一些算法的同学看到题目的时候就会反射般的想到双指针,可是四数之和不同于三数之和,我们怎么样去用双指针做呢。

在做三数之和的时候我们可以通过锁定一个数字,在进行左界右界的确定,
在确定的范围中,寻找这个数字,那么我们将之泛化到四数之和中,既然
三数之和我们确定了一个数字,那么在四数之和中,我们确定两个数字。
锁定两个数字之和,确定左界和右界对范围内搜索。ok,思路明确,我们
考虑特殊情况。

先对数组排序,使之为升序,这里可以使用冒泡,快排,选排,等等,任意选择。

  • 我们考虑,如果我们目前遍历到的数字,从第i个开始,往后三个共四个数字相加,若是大于目标值,那么很明显,这个数组中已经找不到更小的组合了,因此直接返回空。
  • 假设我们已经锁定第一个数字,而我们的确定的右界,第n个,第n-1个,第n-2个数字,与第一个数字相加,已经小于了target,那么很明显我们直接跳过这次循环,让这个数字走向更大的数字才可以搜索得到。
  • 我们需要考虑去重的问题,排序之后重复的数字都是在一块的,因此我们只要判断上一次锁定的是否与这一次一样,若一样就跳过。
  • 这样我们就找到了两个continue的条件和一个break的条件。
  • 在锁定第二个数字的遍历过程中,我们同样重复以上的过程,那么我们就可以避免很多次无用的迭代。

c代码:


/*力扣 四数之和 c by ksks14 2020/11/10 13:31*/
/*思路,快排后利用双指针双面夹击,在思路上与三数之和几乎一样*/
#define maxsize 2000
int compare(const void* a, const void* b) {
    return *(int*)a - *(int*)b;
}
int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes){
	int **answer=(int**)malloc(sizeof(int*)*maxsize);
	*returnColumnSizes=(int*)malloc(sizeof(int)*maxsize);
	*returnSize=0;//初始化需要的变量
	if(numsSize<4)//判断特殊情况 
		return answer;
	qsort(nums,numsSize,sizeof(int),compare);
	for(int i=0;i<numsSize-3;i++){//第一个指针 
		if((i>0&&nums[i]==nums[i-1])||(nums[i]+nums[numsSize-3]+nums[numsSize-2]+nums[numsSize-1]<target)) 
			continue;
		if(nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target)//求前四个数之和,若是大于target则根本没有符合的数字 
			break;
		//考虑两种特殊情况 
		for(int j=i+1;j<numsSize-2;j++){//在i+1~len-2的范围搜索 
			if((j>i+1&&nums[j]==nums[j-1])||(nums[i]+nums[j]+nums[numsSize-2]+nums[numsSize-1]<target))
				continue;
			if(nums[i]+nums[j]+nums[j+1]+nums[j+2]>target)
				break;
			int l=j+1,r=numsSize-1;
			while(l<r){
				if(target==nums[i]+nums[j]+nums[l]+nums[r]){
					int *line=(int*)malloc(sizeof(int)*4);//动态开辟一个数组空间
					line[0]=nums[i],line[1]=nums[j],line[2]=nums[l],line[3]=nums[r]; 
					answer[(*returnSize)]=line;
					(*returnColumnSizes)[(*returnSize)++]=4;
					while(l<r&&nums[l]==nums[l+1])
						l++;
					while(r>l&&nums[r]==nums[r-1])
						r--;
					l++,r--;
				}
				else if(target>nums[i]+nums[j]+nums[l]+nums[r]) l++;
				else r--;
			}
		}
	}
	return answer;
}

python代码:(python思路与c相同,因此我借用网友代码,懒得动手😂)

class Solution:
    def fourSum(self, nums, target):
        ans = []
        nums.sort()
        len_nums = len(nums)
        table = {val: index for index, val in enumerate(nums)}
        # 枚举前三个数
        for i in range(len_nums-3):
            if i > 0 and nums[i] == nums[i-1]:
                continue
            if nums[i] * 4 > target:
                break
            if nums[i] + 3 * nums[-1] < target:
                continue
            for j in range(i + 1, len_nums-2):
                if j > i + 1 and nums[j] == nums[j-1]:
                    continue
                if nums[i] + 3*nums[j] > target:
                    break
                if nums[i] + nums[j] + 2*nums[-1] < target:
                    continue
                for k in range(j + 1, len_nums-1):
                    if k > j + 1 and nums[k] == nums[k - 1]:
                        continue
                    key = target - nums[i] - nums[j] - nums[k]
                    if table.get(key, -1) > k:
                        ans.append([nums[i], nums[j], nums[k], key])#key已经成为我们需要的值了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是力扣(LeetCode)上的经典问题:两数之和(Two Sum)的 C 语言解法。 ```c #include <stdio.h> #include <stdlib.h> int* twoSum(int* nums, int numsSize, int target, int* returnSize) { int i, j; int* result = (int*)malloc(sizeof(int) * 2); *returnSize = 2; for (i = 0; i < numsSize - 1; i++) { for (j = i + 1; j < numsSize; j++) { if (nums[i] + nums[j] == target) { result[0] = i; result[1] = j; return result; } } } return NULL; } int main() { int nums[] = {2, 7, 11, 15}; int target = 9; int returnSize; int* result = twoSum(nums, sizeof(nums) / sizeof(nums[0]), target, &returnSize); if (result != NULL) { printf("[%d, %d]\n", result[0], result[1]); free(result); } return 0; } ``` 这个程序首先定义了一个函数 `twoSum()`,它接受一个整数数组 `nums`,数组的长度 `numsSize`,目标值 `target` 和一个指向整数变量的指针 `returnSize`。这个函数的目的是在给定数组中找到两个数,它们的和等于目标值,并返回这两个数的下标。 函数内部使用了两个嵌套的循环来枚举数组中的所有可能的组合,并检查它们的和是否等于目标值。如果找到了符合条件的组合,就把它们的下标存储在一个动态分配的整数数组中,并返回这个数组的指针。如果没有找到符合条件的组合,就返回空指针。 在 `main()` 函数中,我们定义了一个测试用例,即整数数组 `{2, 7, 11, 15}` 和目标值 `9`。然后我们调用 `twoSum()` 函数,传入这个测试用例,并打印出返回的结果。 值得注意的是,我们在 `twoSum()` 函数内部动态分配了一个整数数组 `result`,然后在 `main()` 函数中使用 `free()` 函数释放了它的内存,以避免内存泄漏。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值