4.21算法

目录

leetcode49:字母异位词分组

题目

示例

解题思路

代码实现

leetcode349:两个数组的交集

题目

示例

解题思路

代码实现 


leetcode49:字母异位词分组

题目

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:

输入: strs = [""]
输出: [[""]]

示例 3:

输入: strs = ["a"]
输出: [["a"]]

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 仅包含小写字母

解题思路

1、对字符串数组中的每个单词按照有a-z的顺序排序
2、以单词为key加入哈希
     每创建一个新的节点,就在该节点中记录返回时的下标位置同(*returnSize)结合
     发现相同key时,记录本key出现次数 == 节点内记录单词下标,该下标同原字符串数组下标结合
3、遍历哈希 将每个节点中的单词->出现的次数(对应的下标)分组取出

代码实现

typedef struct hashtable
{
    char key[102];  
    int index[100]; 
    int count;        
    int xb;        
    UT_hash_handle hh;
}Node;

 

int cmp(const void* a_, const void* b_)
{
    char a=*(char*)a_;char b=*(char*)b_; 
    return a-b;
}
char*** groupAnagrams(char** strs, int strsSize, int* returnSize, int** returnColumnSizes) {
    if(strsSize == 0) {
        *returnSize = 0;
        return NULL;
    }
    Node* arr = NULL;
    *returnSize = 0;    
    for (int i = 0; i < strsSize; i++)
    {
        char* temstrs = (char *)malloc(sizeof(char)*(strlen(strs[i])+1));
        strcpy(temstrs, strs[i]);   
        qsort(temstrs, strlen(temstrs), sizeof(char), cmp); 
        Node* tm = NULL;    
        HASH_FIND_STR(arr, temstrs, tm);   
        if (tm == NULL)       //新结点    
        {
            tm = (Node*)malloc(sizeof(Node));
            strcpy(tm->key, temstrs);
            tm->count = 0;    //首次出现记0
            tm->xb = (*returnSize)++;  //记录返回下标,并更新*returnSize
            tm->index[(tm->count)++] = i; //记录出现在该key中的单词对应的 strs中的下标
            HASH_ADD_STR(arr, key, tm);    //加入链表
        }
        else
            tm->index[(tm->count)++] = i; //重复出现只更新出现次数 和 记录单词在strs中的下标
        

    }

    char*** res = (char***)malloc(sizeof(char**) * (*returnSize));  
    *returnColumnSizes = (int*)malloc(sizeof(int) * (*returnSize)); //该数组记录每行出现单词的个数
	Node* tm;   //临时节点指向s->next
	Node* s;    //起始指向头节点
	HASH_ITER(hh, arr, s, tm) {
		res[s->xb] = (char**)malloc(sizeof(char*) * (s->count));     //为每一行字符串指针分配空间
		for (int j = 0; j < s->count; j++)
		{
            res[s->xb][j] = strs[s->index[j]];
		}
		(*returnColumnSizes)[s->xb] = s->count;  //每行的单词数量就是该节点出现的次数
        HASH_DEL(arr,s);
        free(s);
	}
   
    return res;
}

leetcode349:两个数组的交集

题目

给定两个数组 nums1 和 nums2 ,返回 它们的 交集

 输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

提示:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

解题思路

排序+双指针法

首先对两个数组进行排序,然后使用两个指针遍历两个数组。

初始时,两个指针分别指向两个数组的头部。每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,且该数字不等于 pre,将该数字添加到答案并更新 pre 变量,同时将两个指针都右移一位。当至少有一个指针超出数组范围时,遍历结束。

代码实现 

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */

int cmp(void* a, void* b) {
    return *(int*)a - *(int*)b;
}

int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize) {
    qsort(nums1, nums1Size, sizeof(int), cmp);
    qsort(nums2, nums2Size, sizeof(int), cmp);
    *returnSize = 0;
    int index1 = 0, index2 = 0;
    int* intersection = malloc(sizeof(int) * (nums1Size + nums2Size));
    while (index1 < nums1Size && index2 < nums2Size) {
        int num1 = nums1[index1], num2 = nums2[index2];
        if (num1 == num2) {
            if (!(*returnSize) || num1 != intersection[(*returnSize) - 1]) {
                intersection[(*returnSize)++] = num1;
            }
            index1++;
            index2++;
        } else if (num1 < num2) {
            index1++;
        } else {
            index2++;
        }
    }
    return intersection;
}

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值