Day6 哈希表part1(day5休息)

Day6

前言(哈希表)

所谓哈希表,能用的数据结构有三:数组、Set (集合)、Map (映射)。
一般哈希表都是用来快速判断一个元素是否出现集合里。也就是在“查找”操作上节省时间。用空间换取时间。
在Java中,利用哈希表实现的为HashSet与HashMap。相较于由红黑树实现的,具有时间复杂度更低( O ( 1 ) O(1) O(1))、数值无序的特点。

一、242.有效的字母异位词

文章链接

1. 思路分析

本题运用了哈希方法中的数组结构。

通过定义一个长度为26的数组,可以轻松将26个小写字母分别对应到一个内存里,并以 O ( 1 ) O(1) O(1)的代价将它们找到。

第一个字符串遍历到了一个字母就在数组对应位置+ +,第二个字符串对应- -。最后若该数组全部元素都为0,则说明两个字符串是字母异位词。

2. 解法分析

首先要注意Java语法的不同:

  • string求字符个数用length()。
    (数组length是自身属性,无需括号,但String的length是方法,要加括号。)
  • string求第n个字符用charAt()方法。(不能用string[n])

其次也没什么注意的了,写就是了。
java的字符也能进行数值运算。

3. 代码展示

class Solution {
    public boolean isAnagram(String s, String t) {
        if (s.length() != t.length())
        //String 取字符长度,length是方法,要在后面加括号!!!(数组length是自身属性)
            return false;
        int[] list = new int[26];
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) >= 'a' && s.charAt(i) <= 'z') {
                list[(int)(s.charAt(i) - 'a')]++;
            }
            //取String的第n个字符,要用string.charAt(n)这个方法!!!
            if (t.charAt(i) >= 'a' && t.charAt(i) <= 'z') {
                list[(int)(t.charAt(i) - 'a')]--;
            }
        }
        for (int i = 0; i < list.length; i++) {
            if (list[i] != 0)
                return false;
        }
        return true;
    }
}

二、349. 两个数组的交集

文章链接

1. 思路分析

“计算交集、输出数组元素唯一、不考虑顺序。”

从题目结果的要求看来,后两项说明我们可以用HashMap剔除重复数据,并且忽略顺序带来的影响。

而计算交集的暴力解法自然是两个for循环, O ( n 2 ) O(n^2) O(n2)的复杂度。其中,一个 O ( n ) O(n) O(n)的来源就是通过遍历数组的方法在数组中找一个数

这样我们该想到,我们可以用哈希表,在“查找”操作上省下时间

2. 解法分析

用到了两个哈希集合

  1. 主要就是哈希表的调用。先把数组一转换成哈希集合,这样数组二在搜索是否含有相同元素时只需要 O ( 1 ) O(1) O(1)的时间。

  2. 一旦搜到相同元素,就将其放进另一个结果哈希集合中,主要看重它不会重复添加的特点。

  3. 最后因为要求输出int[]数组,因此需要把哈希集合转化成数组。

感觉对java特殊数据结构与API的调用、原理、应用还不甚了解,应该多去学习。

3. 代码展示

import java.util.HashSet;

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> nums1_set = new HashSet<Integer>(), 
        result = new HashSet<Integer>();
        for (int i : nums1) {
            nums1_set.add(i);
        }
        for (int i : nums2) {
            if (nums1_set.contains(i))
                result.add(i);
        }
        //return result.stream().mapToInt(x -> x).toArray();
        int[] arr = new int[result.size()];
        int j = 0;
        for (int i : result) {
            arr[j++] = i;
        }
        return arr;
    }
}

三、202. 快乐数

文章链接

1. 思路分析

本题比较特殊的地方就是 该数不是快乐数的判断。关键词在于无限循环。一旦之前出现过的sum再次出现,那么就说明该数不是快乐数了
而一旦出现“要快速判断一个元素是否出现集合里”的时候,就应该考虑哈希表了。

2. 解法分析

利用哈希表存储所有的sum,一旦出现重复就返回false。
快乐数求法没什么好讲的。

3. 代码展示

import java.util.HashSet;

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        while (true){
            int sum = 0;
            int n1 = n;
            while (n1 != 0) {
                int t = n1 % 10;
                sum += t * t;
                n1 /= 10;
            }
            if (sum == 1)
                return true;
            if (set.contains(sum))
                return false;
            n = sum;
            set.add(sum);
        }
    }
}

四、1. 两数之和

文章链接

1. 思路分析

做到这里方才领悟了运用哈希表的原因,因为要从找数上省时间!从 O ( n ) O(n) O(n) O ( 1 ) O(1) O(1)啊!
这道题如果用两层for循环,就是妥妥的 O ( n 2 ) O(n^2) O(n2)。但是如果省略一层从数组里遍历找数的for循环,将其用哈希表替代,那么时间复杂度就成了 O ( n ) O(n) O(n)了。

暴力解法依然是两层for循环,排列组合搜就完了。而我们仍然要尝试从“查找”这里省下时间。

由于题目要求最后要返回下标,所以必须把数值和索引一起存起来,能够通过数值找到索引。因此本题数据结构应该使用HashMap

若像第二题那样直接就把数组爆改哈希表,然后数组遍历,挨个从哈希表里搜,在这里会导致一个问题:我们是把数值作为键存起来的,而在HashMap中,键是独一无二的。所以每个数值只能存一次。如果结果是两个相同数值相加,就必须在数组里找和在map中存的索引不一样的相同数值。

而最节省时间的方法,其实是遍历一个存入一个,一遍就过,也避免了上述问题。然后当前数值在map里找之前遍历过的数值。比上述的方法更简约。

2. 解法分析

要牢记哈希表的方法。

  • HashMap: containsKey(), put(, ), get(), size()
  • HashSet: contains(), add(), size()

3. 代码展示

import java.util.HashMap;

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(target - nums[i])) {
                int[] result = new int[2];
                result[0] = i;
                result[1] = map.get(target - nums[i]);
                return result;
            }
            map.put(nums[i], i);
        }
        return null;
    }
}

五、总结

哈希表啊,就是在“查找”操作上节省时间。

遇到“需要快速判断一个元素是否出现集合里”的操作,就想着去用哈希表的数据结构,实现 O ( 1 ) O(1) O(1)的查找速度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值