法一:记忆化递归
int climbStairsRecursive(int n, int* memo) {
if (n <= 2) {
return n;
}
if (memo[n] > 0) {
return memo[n];
}
memo[n] = climbStairsRecursive(n - 1, memo) + climbStairsRecursive(n - 2, memo);
return memo[n];
}
int climbStairs(int n) {
int* memo = (int*)malloc((n + 1) * sizeof(int));
if (memo == NULL) {
return -1; // 内存分配失败
}
memset(memo, 0, (n + 1) * sizeof(int));
int result = climbStairsRecursive(n, memo);
free(memo);
return result;
}
法二:动态规划
int climbStairs(int n) {
int p = 0, q = 0, r = 1;
for (int i = 1; i <= n; ++i) {
p = q;
q = r;
r = p + q;
}
return r;
}
尽管代码中没有明确地使用一个数组来存储状态,但是动态规划的核心思想仍然被运用了:将问题分解成子问题,利用已经求解过的子问题的解来求解当前问题。
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
int hash[1000] = {0}; // 将 hash 数组初始化为 0
int* res = (int*)malloc(sizeof(int) * nums1Size); // 根据 nums1 的大小来动态分配内存
*returnSize = 0; // 初始化返回数组的大小为 0
// 遍历 nums1,将 nums1 中的元素作为 hash 数组的下标,标记出现过的数字
for(int i = 0; i < nums1Size; i++) {
hash[nums1[i]] = 1;
}
// 遍历 nums2,如果 nums2 中的元素在 hash 中出现过,则将其添加到返回数组中
for(int j = 0; j < nums2Size; j++) {
if(hash[nums2[j]] == 1) {
res[(*returnSize)++] = nums2[j];
hash[nums2[j]] = 0; // 避免重复添加相同的数字,这里很巧妙,添加了一次将hash对应改为0
//下一次就算是相同的数字也匹配不了了
}
}
return res;
}
struct hashTable{
int key;
int val;
UT_hash_handle hh;
};
int fourSumCount(int* nums1, int nums1Size, int* nums2, int nums2Size, int* nums3, int nums3Size, int* nums4, int nums4Size){
struct hashTable*hashtable=NULL;
for(int i=0;i<nums1Size;i++)
{
for(int j=0;j<nums2Size;j++)
{
int ikey=nums1[i]+nums2[j];
struct hashTable*tmp;
HASH_FIND_INT(hashtable,&ikey,tmp);
if(!tmp)
{
struct hashTable*tmp=malloc(sizeof(struct hashTable));
tmp->key=ikey;
tmp->val=1;
HASH_ADD_INT(hashtable,key,tmp);
}
else
{
tmp->val++;
}
}
}
int ans=0;
for(int i=0;i<nums3Size;i++)
{
for(int j=0;j<nums4Size;j++)
{
int ikey=-(nums3[i]+nums4[j]);
struct hashTable*tmp;
HASH_FIND_INT(hashtable,&ikey,tmp);
if(tmp)
{
ans+=tmp->val;
}
}
}
return ans;
}
先遍历A,B再遍历C,D算法时间复杂度为n的平方,先遍历A,再遍历B,C,D算法时间复杂度是n的三次方,所以我们采用两个for循环比较好
key表示节点的值,val表示这个值在两个数组A,B组合出现过几次
第一个两重for循环先遍历所有A,B数组的所有值,然后记录次数
第二个两重for循环也同样遍历所有C,D所能构成的值,如果其相反数在哈希表中可以找的到的话,就ans加上第一个双层for记录的出现的次数
参考:【学透哈希表,map使用有技巧!LeetCode:454.四数相加II-哔哩哔哩】 https://b23.tv/diFkLwW
void HASH_ADD_INT(hh, head, add);
其中:
hh
是哈希表中用于链接的哈希结构体的字段名。head
是指向哈希表的指针的名称。add
是要添加到哈希表中的结构体节点的指针。
在您的代码中,HASH_ADD_INT(hashtable, key, tmp);
的作用是将指向结构体节点 tmp
的指针添加到名为 hashtable
的哈希表中。key
是结构体中用于作为键值的整数字段的名称。