Leetcode题库 1.两数之和(C实现)

一、排序法

1、解析/思路

Array_Merge(int* head,int low,int high,int* head1,int low1,int high1,int L,int Step_L,int Bool)
对两有序数组head、head1进行有序合并
Mer_Sort(int* head,int low,int high,int Step_L,int Bool)
对数组head进行二路归并
Seekaim(int* nums, int aim, int left, int right)
在数组nums的[left,right]区间查找aim,若存在则返回其下标,否则返回-1

流程:
二路归并创建nums的有序数组Temp
遍历Temp,在Temp的[i+1,numsSize]查找target-Temp[i]
若查询成功,则说明数组nums中存在两数之和等于target,最后在数组nums中寻找两数的下标
若查询失败,则说明数组nums中不存在两数之和等于target

2、代码

//有序数组调整
void Array_Merge(int* head,int low,int high,int* head1,int low1,int high1,int L,int Step_L,int Bool){
    //i(逻辑),low+i*Step_L(实际)
    //第一个数组最后的位置为((high-low)/Step_L)(逻辑),high(实际),长度:(high-low)/Step_L+1
    //第二个数组最后的位置为((high1-low1)/Step_L)(逻辑),high1(实际),长度:(high1-low1)/Step_L+1 
    //复制
    int Temp[((high-low)/Step_L+1)+((high1-low1)/Step_L+1)];//临时数组
    int i=0,j=low,k=low1;//i指向Temp,指针j指向第1个数组,指针k指向第2个数组
    if(Bool){//有序数组为从小到大
        while(i<((high-low)/Step_L+1)+((high1-low1)/Step_L+1) && (j<=high || k<=high1)){
            if(k>high1){//当第二个数组指针k越界说明第二个数组已经安排完毕
                Temp[i]=head[j];
                j+=Step_L;
                i++;
                continue;
            }
            if(j>high){//当第一个数组指针j越界说明第一个数组已经安排完毕
                Temp[i]=head[k];
                k+=Step_L;
                i++;
                continue;
            }
            if(head[j]<=head1[k]){//选择两指针中更小的数据
                Temp[i]=head[j];
                j+=Step_L;
            }
            else{
                Temp[i]=head[k];
                k+=Step_L;
            }
            i++;
        }
    }
    else{//有序数组从大到小
        while(i<((high-low)/Step_L+1)+((high1-low1)/Step_L+1)  && (j<=high || k<=high1)){
            if(k>high1){//当第二个数组指针k越界说明第二个数组已经安排完毕
                Temp[i]=head[j];
                j+=Step_L;
                i++;
                continue;
            }
            if(j>high){//当第一个数组指针j越界说明第一个数组已经安排完毕
                Temp[i]=head[k];
                k+=Step_L;
                i++;
                continue;
            }
            if(head[j]>=head1[k]){//选择两指针中更小的数据
                Temp[i]=head[j];
                j+=Step_L;
            }
            else{
                Temp[i]=head[k];
                k+=Step_L;
            }
            i++;
        }
    }
    
    i=0;
    while(i<((high-low)/Step_L+1))//将第一个数组复制到head
    {
        head[low+i*Step_L]=Temp[i];i++;}
    
    while(i<((high-low)/Step_L+1)+((high1-low1)/Step_L+1))//将第二个数组复制到head
    {
        head1[low1+(i-((high-low)/Step_L+1))*Step_L]=Temp[i];i++;}
}

//二路归并排序
void Mer_Sort(int* head,int low,int high,int Step_L,int Bool){
    int Shigh=low+(((high-low+1)/Step_L)-1+(((high-low+1)%Step_L)!=0))*Step_L;
    int L=(Shigh-low)/Step_L+1;
    if(L>2){
        Mer_Sort(head,low,low+((L+1)/2-1)*Step_L,Step_L,Bool);
        Mer_Sort(head,low+(((L+1)/2-1)+1)*Step_L,Shigh,Step_L,Bool);
    }
    if(L>1)Array_Merge(head,low,low+((L+1)/2-1)*Step_L,head,low+(((L+1)/2-1)+1)*Step_L,Shigh,L,Step_L,Bool);
}

//二分查找
int Seekaim(int* nums, int aim, int left, int right) {
    //在[l,r]搜寻aim的位置,-1:不存在
    if(nums[left] <= aim && aim <= nums[right]) {
        while(left < right) {
            if(nums[(left+right)/2] < aim) {
                left = (left+right)/2+1;
            }else {
                right = (left+right)/2;
            }
        }
    }
    return nums[left] == aim?left: -1;
}

int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int* Temp = malloc(sizeof(int) * numsSize);
    for(int i=0;i<numsSize;i++){
        Temp[i]=nums[i];
    }
    Mer_Sort(Temp,0,numsSize-1,1,1);
    for(int i=0;i<numsSize-1;i++){
        int Index=Seekaim(Temp,target-Temp[i],i+1,numsSize-1);
        //printf("\na:%d b:%d Index:%d",Temp[i],target-Temp[i],Index);
        if(Index!=-1){
            int* ret = malloc(sizeof(int) * 2);
            ret[0]=Temp[i];
            ret[1]=target-Temp[i];
            *returnSize=2;
            //printf("\n%d %d",ret[0],ret[1]);
            int t0,t1;
            for(int j=0;j<numsSize;j++){
                if(nums[j]==ret[0]) {ret[0]=j;break;}
            }
            for(int j=0;j<numsSize;j++){
                if(nums[j]==ret[1] && j!=ret[0]) {ret[1]=j;break;}
            }
            //printf("\n%d %d",ret[0],ret[1]);
            return ret;
        }
    }
    *returnSize=0;
    return NULL;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值