@ 代码随想录算法训练营第二周(C语言)|Day7(哈希表)

@ 代码随想录算法训练营第二周(C语言)|Day7(哈希表)

Day7、哈希表(包含题目 454.四数相加II 383. 赎金信 15. 三数之和 18. 四数之和 )

454.四数相加II

题目描述

给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。

为了使问题简单化,所有的 A, B, C, D 具有相同的长度 N,且 0 ≤ N ≤ 500 。所有整数的范围在 -2^28 到 2^28 - 1 之间,最终结果不会超过 2^31 - 1 。

题目解答

struct list{
    int key;
    int val;
    struct list*next;
};
void hashpush(struct list *head,int key,int val){
    struct list *temp=malloc(sizeof(struct list));
    temp->key=key;
    temp->val=val;
    temp->next=head->next;
    head->next=temp;
}

struct list*hashFind(struct list*head,int key){
    for(struct list*it=head;it->next;it=it->next){
        if(it->next->key==key){
            return it->next;
        }
    }
    return NULL;
}


typedef struct hashmap{
    struct list*data;
}hashmap;

const int base=100;
int hash(int val){
    return fabs(val%base);
}
hashmap*hashMapCreate(){
    hashmap*obj=malloc(sizeof(hashmap));
    obj->data=malloc(sizeof(struct list)*base);
    for(int i=0;i<base;i++){
        obj->data[i].key=0;
        obj->data[i].val=0;
        obj->data[i].next=NULL;
    }
    return obj;
}



int fourSumCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* nums3, int nums3Size, int* nums4, int nums4Size){

    hashmap*obj=hashMapCreate();
    for(int i=0;i<nums1Size;i++){
        for(int j=0;j<nums2Size;j++){
            int h=hash(nums1[i]+nums2[j]);
            struct list*tmp=hashFind(&(obj->data[h]),nums1[i]+nums2[j]);
            if(!tmp){
                tmp=malloc(sizeof(struct list));
                tmp->key=nums1[i]+nums2[j];
                tmp->val=1;
                hashpush(&(obj->data[h]),tmp->key,tmp->val);
            }
            else{
                tmp->val++;
            }
        }
    }
    int count=0;
    for(int m=0;m<nums3Size;m++){
        for(int n=0;n<nums4Size;n++){
            int h=hash(-(nums3[m]+nums4[n]));
            struct list*tmp=hashFind(&(obj->data[h]),-(nums3[m]+nums4[n]));
            if(tmp){
                count+=tmp->val;
            }
        }
    }
    return count;
}

题目总结

注意创建哈希表。

383. 赎金信

题目描述

给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。

题目解答

bool canConstruct(char* ransomNote, char* magazine) {
    int*hashmap[26]={0};
    int nums1=strlen(ransomNote);
    int nums2=strlen(magazine);

    for(int i=0;i<nums1;i++){
        hashmap[ransomNote[i]-'a']++;
    }
    for(int j=0;j<nums2;j++){
        if(hashmap[magazine[j]-'a']==0){

            continue;
        }else{
            hashmap[magazine[j]-'a']--;
        }
    }
    int k=0;
    while(k<=25&&hashmap[k]==0){
        k++;
    }
    if(k==26){
        return true;
    }else{
        return false;
    }
}

题目总结

要注意 hashmap[magazine[j]-‘a’ ]的key值表示方式。

15. 三数之和

题目描述

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

题目解答

void quickSort(int *nums,int left,int right){
    if(left>=right){
        return;
    }
    int k=nums[left];
    int i=left;
    int j=right;
    while(i<j){
        while(i<j&&nums[j]>=k){
            j--;
        }
        nums[i]=nums[j];
        while(i<j&&nums[i]<=k){
            i++;
        }
        nums[j]=nums[i];

    }
    nums[i]=k;
    quickSort(nums,left,i-1);
    quickSort(nums,i+1,right);
}

int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
    //数组排序
    int left=0;
    int right=numsSize-1;
    quickSort(nums,left,right);
    //排序之后的三数之和操作
    int**res=(int**)malloc(sizeof(int*)*100000);
    int count=0;
    if(numsSize<3){
        *returnSize=0;
        return res;
    }

    for(int i=0;i<numsSize-2;i++){
        if(nums[i]>0){
            break;
        }
        if(i>0&&nums[i]==nums[i-1]){
            continue;
        }
        int left1=i+1;
        int right1=numsSize-1;
        while(left1<right1){
            int ans=nums[i]+nums[left1]+nums[right1];
            if(ans>0){
                right1--;
            }else if(ans<0){
                left1++;
            }else{
                int*arr=(int*)malloc(sizeof(int)*3);
                arr[0]=nums[i];
                arr[1]=nums[left1];
                arr[2]=nums[right1];
                res[count++]=arr;
                while(right1>left1&&nums[right1]==nums[right1-1]){
                right1--;
                }
                while(left1<right1&&nums[left1]==nums[left1+1]){
                    left1++;
                }
                left1++;
                right1--;
            }
            
        }
    }

    *returnSize=count;
    *returnColumnSizes=(int*)malloc(sizeof(int)*count);
    for(int i=0;i<count;i++){
        (*returnColumnSizes)[i]=3;
    }
    return res;


}

题目总结

双指针同时要注意剪枝,剪枝的时候要注意越界的问题,不能重复就是要排序。

18. 四数之和

题目描述

题意:给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。。

题目解答

void quickSort(int *nums,int left1,int right1){
    if(left1>=right1){
        return;
    }
    int i=left1;
    int j=right1;
    int k=nums[left1];
    while(i<j){
        while(i<j&&nums[j]>k){
            j--;
        }
        nums[i]=nums[j];
        while(i<j&&nums[i]<k){
            i++;
        }
        nums[j]=nums[i];

    }
    nums[i]=k;
    quickSort(nums,left1,i-1);
    quickSort(nums,i+1,right1);
}

int** fourSum(int* nums, int numsSize, int target, int* returnSize, int** returnColumnSizes) {
    int left1=0;
    int right1=numsSize-1;
    quickSort(nums,left1,right1);

     //数组排序
    int left=0;
    int right=numsSize-1;
    quickSort(nums,left,right);
    //排序之后的三数之和操作
    int**res=(int**)malloc(sizeof(int*)*100000);
    int count=0;
    if(numsSize<4){
        *returnSize=0;
        return res;
    }
    for(int k=0;k<numsSize-3;k++){
        if(nums[k]>target&&nums[k+1]>0){
            break;
        }
        if(k>0&&nums[k]==nums[k-1]){
            continue;
        }
        for(int i=k+1;i<numsSize-2;i++){
            if(i>k+1&&nums[i]==nums[i-1]){
                continue;
            }
            int left1=i+1;
            int right1=numsSize-1;
            while(left1<right1){
                int ans=nums[k]+nums[i]+nums[left1]+nums[right1]-target;
                if(ans>0){
                    right1--;
                }else if(ans<0){
                    left1++;
                }else{
                    int*arr=(int*)malloc(sizeof(int)*4);
                    arr[0]=nums[k];
                    arr[1]=nums[i];
                    arr[2]=nums[left1];
                    arr[3]=nums[right1];
                    res[count++]=arr;
                    while(right1>left1&&nums[right1]==nums[right1-1]){
                    right1--;
                    }
                    while(left1<right1&&nums[left1]==nums[left1+1]){
                        left1++;
                    }
                    left1++;
                    right1--;
                }
                
            }
        }


    }

        

    *returnSize=count;
    *returnColumnSizes=(int*)malloc(sizeof(int)*count);
    for(int i=0;i<count;i++){
        (*returnColumnSizes)[i]=4;
    }
    return res;
}

题目总结

快排加多一次的循环,为啥显示超出时间限制呢,不懂。

你可能感兴趣的:(算法,c语言,散列表)