力扣:49. 字母异位词分组

知识点:

散列函数

散列函数能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位:

  1. 直接寻址法:取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a*key + b,其中a和b为常数(这种散列函数叫做自身函数)

  2. 数字分析法:分析一组数据,比如一组员工的出生年月日,这时我们发现出生年月日的前几位数字大体相同,这样的话,出现冲突的几率就会很大,但是我们发现年月日的后几位表示月份和具体日期的数字差别很大,如果用后面的数字来构成散列地址,则冲突的几率会明显降低。因此数字分析法就是找出数字的规律,尽可能利用这些数据来构造冲突几率较低的散列地址。

  3. 平方取中法:取关键字平方后的中间几位作为散列地址。

  4. 折叠法:将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址。通常针对较长的关键字。

  5. 随机数法:选择一随机函数,取关键字的随机值作为散列地址,通常用于关键字长度不同的场合。

  6. 除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key MOD p, p<=m。不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生同义词。

查找效率

查找过程中,关键码的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。因此,影响产生冲突多少的因素,也就是影响查找效率的因素。影响产生冲突多少有以下三个因素:

  1. 散列函数是否均匀;

  2. 处理冲突的方法;

  3. 散列表的装填因子。

  散列表的装填因子定义为:α= 填入表中的元素个数 / 散列表的长度

  α是散列表装满程度的标志因子。由于表长是定值,α与“填入表中的元素个数”成正比,所以,α越大,填入表中的元素较多,产生冲突的可能性就越大;α越小,填入表中的元素较少,产生冲突的可能性就越小。

  实际上,散列表的平均查找长度是装填因子α的函数,只是不同处理冲突的方法有不同的函数。

加法哈希:

常用于字符串,将字符串中的每个字符转换为其对应的 ASCII 值,然后进行加法运算来生成哈希值。

int hash(char* str) {int hashValue = 0;for (int i = 0; str[i] != '\0'; i++) {hashValue += str[i];}return hashValue;
}

这里使用了一个简单的散列函数,它是一个基于质数的乘法散列函数。具体来说,散列函数的实现如下:

//对字符串进行哈希
int hash(char* str) {int hashValue = 0;for (int i = 0; str[i] != '\0'; i++) {hashValue = (hashValue * PRIME + str[i]) % 1000007;}return hashValue;
}

在这里,PRIME 是一个选择的质数,它有助于减少碰撞。我们遍历字符串的每个字符,并用它们更新 hashValue。由于我们对 hashValue 取模 1000007,所以返回的散列值会在 01000006 之间。

位运算哈希:

先移位,然后再进行各种位运算是这种类型Hash函数的主要特点。

int bitHash(char* str) {int hashValue = 0;for (int i = 0; str[i] != '\0'; i++) {hashValue = (hashValue << 5) + str[i] ^ hashValue;}return hashValue;
}

乘法哈希:

利用了乘法的不相关性(乘法的这种性质,最有名的莫过于平方取头尾的随机数生成算法,虽然这种算法效果并不好)。

FNV(Fowler–Noll–Vo)哈希算法是一个著名的乘法哈希算法,常用于字符串哈希。它是一种非常简单但效果很好的哈希算法。

#include <stdint.h>uint32_t fnv1a(char* str) {uint32_t hash = 2166136261u; // FNV偏移基础值while (*str) {hash ^= (unsigned char)*str++;hash *= 16777619u; // FNV素数}return hash;
}

字符串操作:

#include<string.h>

字符串复制

strdup 是一个 C 语言函数,用于复制一个字符串。

strdup 函数会分配足够的内存来存储传入的字符串,并将原始字符串复制到新分配的内存中。然后返回指向新分配的字符串的指针。

char* copy = strdup(str);

free(copy);

strdup 可以用于创建字符串的副本,以便稍后使用和修改,而不影响原始字符串。

将malloc和赋值操作合二为一

排序:

void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));

  • base:指向要排序的数组的指针。
  • nmemb:数组中元素的数量。
  • size:数组中每个元素的大小(以字节为单位)。
  • compar:用于比较两个元素的函数的指针。
int compare(const void* a, const void* b) {return *(char*)a - *(char*)b;
}
 char* str1 = strdup(strs[i]);int len = strlen(str1);//对 str1 中的字符进行排序,这样,具有相同字符的异位词会有相同的排序后的字符串。qsort(str1, len, sizeof(char), compare);

暴力求解:

超出时间限制。

*returnSize记录最终数组有多少个。

returnColumnSize记录最终数组中,每个数组的长度。一维数组。

        result[*returnSize] = (char**)malloc(strsSize * sizeof(char*));

        (*returnColumnSizes)[*returnSize] = 0;

        result[*returnSize][(*returnColumnSizes)[*returnSize]] = strs[i];

        (*returnColumnSizes)[*returnSize] += 1;

/*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int compare(const void* a, const void* b) {return *(char*)a - *(char*)b;
}char*** groupAnagrams(char** strs, int strsSize, int* returnSize, int** returnColumnSizes) {//记录strs中哪个词被找过了int* countstrs = (int*)malloc(strsSize * sizeof(int));//全置为0memset(countstrs, 0, strsSize * sizeof(int));*returnSize = 0;char*** result = (char***)malloc(strsSize * sizeof(char**));*returnColumnSizes = (int*)malloc(strsSize * sizeof(int));for (int i = strsSize-1; i >=0; i--) {if (countstrs[i] == 1) continue;char* str1 = strdup(strs[i]);int len = strlen(str1);//对 str1 中的字符进行排序,这样,具有相同字符的异位词会有相同的排序后的字符串。qsort(str1, len, sizeof(char), compare);result[*returnSize] = (char**)malloc(strsSize * sizeof(char*));(*returnColumnSizes)[*returnSize] = 0;result[*returnSize][(*returnColumnSizes)[*returnSize]] = strs[i];(*returnColumnSizes)[*returnSize] += 1;countstrs[i] = 1;for (int z = i-1; z >=0; z--) {if (countstrs[z] == 1) continue;char* str2 = strdup(strs[z]);if (len != strlen(str2)) {free(str2);continue;}qsort(str2, len, sizeof(char), compare);//现在都顺序排列了int flag=0;for (int j = 0; j < len; j++) {if (str1[j] == str2[j] ) {flag++;}elsebreak;}if (flag==len) {result[*returnSize][(*returnColumnSizes)[*returnSize]] = strs[z];(*returnColumnSizes)[*returnSize] += 1;countstrs[z] = 1;}free(str2);}*returnSize += 1;free(str1);}free(countstrs);return result;
}

哈希:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define PRIME 31typedef struct Node {char* key;char** values;int count;struct Node* next;
} Node;int compare(const void* a, const void* b) {return *(char*)a - *(char*)b;
}//对字符串进行哈希
int hash(char* str) {int hashValue = 0;for (int i = 0; str[i] != '\0'; i++) {hashValue = (hashValue * PRIME + str[i]) % 1000007;}return hashValue;
}Node* createNode(char* key, char* value) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->key = strdup(key);newNode->values = (char**)malloc(1000 * sizeof(char*));newNode->values[0] = strdup(value);newNode->count = 1;newNode->next = NULL;return newNode;
}Node** createHashMap(int size) {Node** table = (Node**)malloc(size * sizeof(Node*));for (int i = 0; i < size; i++) {table[i] = NULL;}return table;
}void insert(Node** table, char* key, char* value, int size) {int index = hash(key) % size;if (table[index] == NULL) {table[index] = createNode(key, value);return;}Node* current = table[index];while (current->next != NULL) {if (strcmp(current->key, key) == 0) {current->values[current->count++] = strdup(value);return;}current = current->next;}if (strcmp(current->key, key) == 0) {current->values[current->count++] = strdup(value);} else {current->next = createNode(key, value);}
}char*** groupAnagrams(char** strs, int strsSize, int* returnSize, int** returnColumnSizes) {*returnSize = 0;Node** hashMap = createHashMap(1000007);*returnColumnSizes = (int*)malloc(strsSize * sizeof(int));char*** result = (char***)malloc(strsSize * sizeof(char**));for (int i = 0; i < strsSize; i++) {char* sortedStr = strdup(strs[i]);qsort(sortedStr, strlen(sortedStr), sizeof(char), compare);insert(hashMap, sortedStr, strs[i], 1000007);free(sortedStr);}for (int i = 0; i < 1000007; i++) {Node* current = hashMap[i];while (current != NULL) {result[*returnSize] = (char**)malloc(current->count * sizeof(char*));for (int j = 0; j < current->count; j++) {result[*returnSize][j] = strdup(current->values[j]);}(*returnColumnSizes)[*returnSize] = current->count;(*returnSize)++;current = current->next;}}for (int i = 0; i < 1000007; i++) {Node* current = hashMap[i];while (current != NULL) {for (int j = 0; j < current->count; j++) {free(current->values[j]);}free(current->values);Node* temp = current;current = current->next;free(temp->key);free(temp);}}free(hashMap);return result;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/818241.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯物联网竞赛_STM32L071_16_EEPROM

仍然是没有考过的知识点 朴素的讲就是板子中一块不会因为断电重启而导致数值初始化的一片地址 要注意的是有时候容易把板子什么写错导致板子什么地址写坏了导致程序无法烧录&#xff0c;这个时候记得一直按flash键烧录&#xff0c;烧录时会报错&#xff0c;点击确定&#xff0…

linux的线程概念

目录 1.原理 2.线程的周边概念 3.创建线程的接口 1.pthread_create 2.pthread_join 3.pthread_detach 4.终止线程 5.C11封装的多线程库 4.线程库的大概结构 5.__thread&#xff08;只能修饰内置类型&#xff09; 6.线程的互斥 1.了解原理 2.加锁 1.接口 2.代码示…

【网络编程】Linux网络内核结构以及分布剖析

hello &#xff01;大家好呀&#xff01; 欢迎大家来到我的网络编程系列之Linux网络内核结构以及分布剖析&#xff0c;在这篇文章中&#xff0c;你将会学习到在Linux内核中如何实现网络数据的输入和输出的&#xff0c;并且我会给出源码进行剖析&#xff0c;以及手绘UML图来帮助…

如何应对Android面试官 -> ActivityManagerService 是怎么启动的?

前言 本章主要讲解下 什么是 AMS&#xff0c;以及它是如何启动的&#xff1b; SystemServer SystemServer 通过按下电源键接通电源之后就会启动 BootRoom&#xff0c;BootRoom 就会拉起一个 BootLoader 程序&#xff0c;此程序会拉起 Linux Kernel「系统内核」&#xff0c;我们…

树 和 二叉树

目录 一、树 1、初识树 2、树的一些概念 3、树的表示形式 二、二叉树 1、初识二叉树 2、两种特殊的二叉树 3、二叉树的性质 4、二叉树的遍历 5、实现一棵二叉树 6、二叉树题目&#xff08;没代码的后面会给补上&#xff09; 一、树 1、初识树 &#xff08;1&…

【Java】图片处理工具ImageMagick简介及其在Java中的应用

ImageMagick是一款强大的图像处理软件&#xff0c;它可以用于创建、编辑、合并和转换图像。它支持超过200种图像格式&#xff0c;并且提供了丰富的功能&#xff0c;包括图像缩放、旋转、裁剪、加水印、添加特效等。ImageMagick还支持批量处理图像&#xff0c;可以通过命令行或者…

浅谈网络代理 proxy

总会有各种各样需要用到代理的场景 比如批量提交漏洞、批量注册、批量扫描.... 简单总结一下 代理简介 IP 代理是一种网络技术&#xff0c;通过这种技术&#xff0c;用户可以隐藏其真实的 IP 地址&#xff0c;并使用另一个 IP 地址来代表自己进行互联网上的活动。IP 代理通常由…

xhci 数据结构

xhci 数据结构 xhci 数据结构主要在手册上有详细的定义&#xff0c;本文根据手册进行归纳总结&#xff1a; 重点关注的包括&#xff1a; device contexttrb ringtrb device context设备上下文 设备上下文数据结构由xHC管理&#xff0c;用于向系统软件报告设备配置和状态信息。…

《CSS 知识点》仅在文本有省略号时添加 tip 信息

html <div ref"btns" class"btns"><div class"btn" >这是一段很短的文本.</div><div class"btn" >这是一段很短的文本.</div><div class"btn" >这是一段很长的文本.有省略号和tip.<…

MongoDB副本集部署(windows)

环境准备 本教程演示mongodb4.4 副本集部署&#xff08;一主两从&#xff0c;伪分布式&#xff09; 节点配置主节点localhost:27017从节点1localhost:27018从节点2localhost:27019 每一个节点&#xff08;实例&#xff09;都创建对应的数据文件&#xff08;data&#xff09;…

MySQL中的存储过程详解(上篇)

使用语言 MySQL 使用工具 Navicat Premium 16 代码能力快速提升小方法&#xff0c;看完代码自己敲一遍&#xff0c;十分有用 拖动表名到查询文件中就可以直接把名字拉进来中括号&#xff0c;就代表可写可不写 目录 1.认识存储过程 1.1 存储过程的作用 1.2 存储过程简介…

OpenHarmony轻量系统开发【13】鸿蒙小车开发

13.1 小车介绍 基于鸿蒙系统 Hi3861 的WiFi小车 首先&#xff0c;我们得有一套WiFi小车套件&#xff0c;其实也是Hi3861 加上电机、循迹模块、超声波等模块。 小车安装完大概是这样&#xff1a; 13.2 电机驱动 我们这里先只做最简单的&#xff0c;驱动小车的电机&#xff…

ModuleNotFoundError: No module named ‘llama_index.readers“解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

怎样将PDF转成PPT,有免费的工具吗?

PDF转换为PPT的需求在现代办公和学习中越来越常见。很多人可能遇到过需要将PDF文件中的内容转移到PPT中以方便编辑和展示的情况。幸运的是&#xff0c;现在市面上有许多工具可以帮助我们实现这一目标&#xff0c;而且其中不乏一些免费的选项。本文将详细介绍如何使用这些免费工…

自然语言处理、大语言模型相关名词整理

自然语言处理相关名词整理 零样本学习&#xff08;zero-shot learning&#xff09;词嵌入&#xff08;Embedding&#xff09;为什么 Embedding 搜索比基于词频搜索效果好&#xff1f; Word2VecTransformer检索增强生成&#xff08;RAG&#xff09;幻觉采样温度Top-kTop-p奖励模…

Python | Leetcode Python题解之第24题两两交换链表中的节点

题目&#xff1a; 题解&#xff1a; class Solution:def swapPairs(self, head: ListNode) -> ListNode:dummyHead ListNode(0)dummyHead.next headtemp dummyHeadwhile temp.next and temp.next.next:node1 temp.nextnode2 temp.next.nexttemp.next node2node1.next…

Hello算法11:排序

https://www.hello-algo.com/chapter_sorting/ 选择排序 初始未排序的区间是[0,n-1]在[0,n-1]中查找最小元素&#xff0c;和索引0交换&#xff0c;此时未排序的区间是[1,n-1]在[1,n-1]中查找最小元素&#xff0c;和索引1交换&#xff0c;此时未排序区间是[2,n-1]以此类推&…

基于springboot+vue+Mysql的藏区特产销售平台

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

TC387实现SPI自通讯

TC387实现SPI自通讯 预期效果&#xff1a; TC387上定义两个SPI通讯接口&#xff0c;一个用于发数据一个用于收数据。准确无误的收到一次数据就对核心板led灯的状态进行一次翻转。 由于实验设备有限&#xff0c;只能想办法通过现有设备进行实验。 实现过程&#xff1a; 最开…