@ 代码随想录算法训练营第二周(C语言)|Day7(哈希表)
给定四个包含整数的数组列表 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;
}
注意创建哈希表。
给定一个赎金信 (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值表示方式。
给你一个包含 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;
}
双指针同时要注意剪枝,剪枝的时候要注意越界的问题,不能重复就是要排序。
题意:给定一个包含 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;
}
快排加多一次的循环,为啥显示超出时间限制呢,不懂。