LeetCode|哈希表简单运用解题

什么是哈希表?

  哈希表,是根据关键码值而直接进行访问的数据结构。

简单但来说是根据在集合内的所有数据所具有的唯一,确定的属性,以此为查找依据,来查找到,并访问该数据内容。
例如:一个学生在学校中的学号是唯一确定的,我们想要了解到该学生的信息,只需要通过学号的查询,就可访问到该学生在学校中的所有信息。哈希表的使用原理与之相似。

如何简单的使用哈希表

由于笔者也是出于初学阶段,仅仅只能通过在LeetCode上面所见到的经典题型进行分析。

  • 给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
    例如:
    s = “I am a student”
    返回 0.
    s = “I love China”,
    返回 2.

在遇到此问题时我们所能最直观的想到的就是通过双层循环,遍历每一次所出现的字符,在之后是否会出现。这样的思路对于这道题来说,是可以解决的,但是同时时间复杂度也是很高的,达到了o(n^2)。因此我们所需要做的就是想办法如何降低时间复杂度。
对于如何降低时间复杂度,我们通过可以建立一个数组,通过牺牲空间,来换取时间来达到降低时间复杂度的目的,在上面所说过,哈希表中需要一个唯一,确定的属性来标识不同的数据,对于字符来说,他们不同的属性就是其ASCLL码。众所周知,字符一共有256个。因此,我们可以申请一个数组ASCLL[256]。用这个数组来记录每个字符出现的个数,最终通过对于数组内容的查看,就可知道每个字符所出现的次数。

程序实现

int firstUniqChar(char * s){
    int arr[256] = {0};    //创建数组
    char *p = s;            //保存字符串首地址
    int r = -1;
    while(*p != '\0')    //单次循环记录每个字符出现的次数
    {
        arr[*p]++;
        p++;
    }
    p = s;
    while(*p != '\0')    //根据字符出现的顺序,遍历出第一个符合要求的字符
    {
        if(arr[*p]==1)
        {
            r = p-s;     //得到改字符的下标
            break;
        }
        p++;
    }
    return r;
}

通过创建数组的使用我们可以发现,我们将循环的嵌套转变为了,多次(2次)循环。时间复杂度也从o(n^2)减少成为了o(n)。

  • 给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。
    示例 1:
    输入: [3,0,1]
    输出: 2
    示例 2:
    输入: [9,6,4,2,3,5,7,0,1]
    输出: 8

这道题与第一道题类似,只是将字符串换成了数组。对于这样道题,最直接的办法就是将数组排序,一次从0开始遍历,找到缺失的那个数字。同样时间复杂的也是o(n^2)。
这道题同样我们也可以根据数组的建立,来找到这个缺失的数字,但是问题在于创建数组,我们需创建多大的,数字不同于字符,字符的个数是一定的,但数字是无限的,但是通过题目我们可以得到,数字所出现的范围是n以内,那好我们只需要一个n大的数组就完全可以满足题目要求。

程序实现

int missingNumber(int* nums, int numsSize){
    int *arr = (int *)malloc(sizeof(int)*(numsSize+1));  //因为数组在创建是需要给定确定的大小,
                                                        //所有我们只能通过动态开辟空间来实现
    memset(arr,-1,sizeof(int)*(numsSize+1));   //对于新开辟空间的初始化很重要,若未初始化,则可能会对最终结果产生影响
    int i = 0;
    for(i = 0; i < numsSize; i++)   //依次遍历,记录下每个数字
    {
        arr[nums[i]] = nums[i];
    }
    for(i = 0; i <= numsSize; i++)
    {
        if(arr[i] != i)  //因为数字从0开始,与只对应的下标相同,所有只要判断下标和其中保存的内容是否相同,
                         //由于有0,所以在初始化是,将里面的所有内容都置为-1
            break;
    }
    free(arr);    //记得释放空间
    return i;
}
  • 给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
    示例 1:
    输入: [1,2,0]
    输出: 3
    示例 2:
    输入: [3,4,-1,1]
    输出: 2

这道题与第二道题做法类似,但却略有却别,我们对于数组的访问只是从0号下标到numsSize-1,但这道题中,所给的数组大小,与其中所给的数字并不都满足这个范围,因此我们需要格外注意,但辛好题目只要求给出没有出现最小的正整数,因此在n大的数组中,没有出现最小的正整数最大就是n+1。因此我们可以根据这个突破口来找到这个数字。

程序实现

int firstMissingPositive(int* nums, int numsSize){
    int *arr = (int *)malloc(sizeof(int)*(numsSize+1));  //开辟空间,因为最大时n+1所以多开辟一个空间
    int i = 0;
    memset(arr,0,sizeof(int)*(numsSize+1));    //初始化内存
    for(i = 0; i < numsSize;i++)    //记录每个在合法下标内出现的数字
    {
        if(nums[i]<=numsSize&&nums[i]>0)
            arr[nums[i]] = 1;
    }
    for(i = 1; i <= numsSize; i++)   //遍历所创建的数组,因为是最小正整数,所以我们从1开始遍历
    {
        if(arr[i]==0)
            break;
    }
    free(arr);     //释放空间
    return i;
}

由于笔者仅仅是初学,所以对于哈希表的使用有限,仅仅只能通过开辟数组来达到使用效果。还请各路大佬多多指点。

你可能感兴趣的:(LeetCode|哈希表简单运用解题)