Leetcode第18题四数之和||C语言

方法:通过遍历固定两位后,对另外两位使用双指针法

void QuickSort(int*nums,int left,int right){//快排
    if(left>right)
       return;
    int i=left;
    int j=right;
    int key=nums[i];
    int temp;
    while(i<j){
        while(i<j&&nums[j]>=key)
            j--;
        while(i<j&&nums[i]<=key)
            i++;
        if(i<j){
            temp=nums[i];
            nums[i]=nums[j];
            nums[j]=temp;
        }      
    }
    nums[left]=nums[i];
    nums[i]=key;
    QuickSort(nums,left,i-1);
    QuickSort(nums,i+1,right);
}


int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes){
   if(numsSize<4){
       *returnSize=0;
       return NULL;
   }//如果总长度小于4,直接返回空
   QuickSort(nums,0,numsSize-1);//快排
   int index=0;
   int **number=(int **)malloc(10000*sizeof(int *));
   for(int i=0;i<numsSize-3;i++){
       if(target>=0&&nums[i]>target)
       //如果target是正数或0,且nums数组最小的数大于target,直接退出循环
           break;
       if(target<=0&&nums[numsSize-1]<target)
       //如果target是负数或0,且nums数组最大的数小于target,直接退出循环
           break;
       if(i>0&&nums[i]==nums[i-1])
       //i如果自增后和上一位的i相同,直接continue
          continue;
       for(int j=i+1;j<numsSize-2;j++){
           if(j>i+1&&nums[j]==nums[j-1])
           //j如果自增后和上一位的j相同,直接continue
              continue;
           int left=j+1;
           int right=numsSize-1;
           //固定j后将left初始化为j+1,right初始化为numsSize-1,遍历时将两个指针向中间移动
           while(left<right){
               long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];//这里要用long,因为测试里有超级超级大的数
               if(sum<target)
                   left++;//如果和小于target,就将left右移一位
               else if(sum>target)
                   right--;//如果和大于target,则将right左移一位
               else{
                   int *array=(int *)malloc(4*sizeof(int));
                   array[0]=nums[i];
                   array[1]=nums[j];
                   array[2]=nums[left];
                   array[3]=nums[right];
                   number[index++]=array;
                   left++;
                   right--;
                   while(left<right&&nums[left]==nums[left-1])
                      left++;
                   while(left<right&&nums[right]==nums[right+1])
                      right--;
               }
           }//while
       }//forj
   }//fori  
   *returnSize=index;
   (*returnColumnSizes)=(int *)malloc(index*sizeof(int));
   for(int i=0;i<index;i++){
       (*returnColumnSizes)[i]=4;
   }
   return number;
}

执行情况
除了每轮循环对i和j用if语句判断是否与上一轮的i和j相同外,也可以考虑建立一个bool类型的变量symbol,每次当sum=target时,将number中每个数组的前三位依次与nums[i],nums[j],nums[left]对比,若sum=target且四个数中前三个跟number某数组前三个数相等,说明第四个数也一定相等,所以对应元素相同,不将这四个数加入number数组
当我试了一下,这个方法效率差的有点多…

代码(放在else中):

symbol=false;
      if(index>0){
          for(int k=0;k<index;k++){
              if(nums[i]==number[k][0]&&nums[j]==number[k][1]&&nums[left]==number[k][2]){
                    symbol=true;
                    break;
               }
           }
      }
      if(symbol){
             right--;
             left++;
             continue;
       }

执行情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值