代码随想录day6

 哈希表理论基础

哈希表也称散列表也在我写过的数据结构那里有所说明

当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。

  • 数组
  • set (集合)
  • map(映射)

当我们想使用哈希法来解决问题时,选择的数据结构通常取决于具体的问题需求:

  • 数组:适用于需要有序存储快速随机访问的情况。但是,数组的大小通常是固定的,而且查找特定元素的时间复杂度依赖于数组是否排序

  • Set(集合):如HashSet,适用于需要存储唯一元素且不需要维护任何特定顺序的情况。在Java中,除了HashSet,还有TreeSet(基于红黑树实现,可以保证元素排序)和LinkedHashSet(基于哈希表和链表实现,可以保证元素的插入顺序)。

  • Map(映射):如HashMap,适用于需要通过键(key)来查找值(value)的情况。Map提供了从唯一键到值的映射,非常适合用来建立索引或者关联不同类型的信息。

HashSet

HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合。

HashSet 允许有 null 值。

HashSet 是无序的,即不会记录插入的顺序。

HashMap

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。

HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。

HashMap 是无序的,即不会记录插入的顺序。

两者区别

HashSetHashMap的主要区别在于:

  • Key和Value的使用HashMap存储键值对(key-value pairs),其中键(key)是唯一的,而值(value)可以重复。HashSet只存储元素(可以看作是键,没有对应的值),并且所有元素都是唯一的。

  • 数据结构:虽然两者都基于哈希表,但是HashMap存储的是键值对,因此每个条目都包含一个键和一个值。而HashSet的每个条目只包含一个值,这个值同时也作为键使用。

  • 接口实现HashMap实现了Map接口,而HashSet实现了Set

卡哥提示

什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考

虑哈希法。 这句话很重要,大家在做哈希表题目都要思考这句话。

 242.有效的字母异位词

思路

由于在ASCCII中,一个字母对应一个数值,建立一个哈希数组,在数组里存储第一个字符串中各个字母出现的次数,再用第二个字符串对应减掉数组的数值,若全为零,则说明两个字符串字母出现的频率相同。

在范围较小的时候用数组,若较大用set,需要key值对应用map

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] hash=new int[26];
        for(int i=0;i<s.length();i++){
            hash[s.charAt(i)-'a']++;//-'a':是利用字符串中字母与a的差值,因为这些差值是固定的,++是记录个数
                        
        }
        for(int i=0;i<t.length();i++){
            hash[t.charAt(i)-'a']--;
        }
         for (int count: hash) {
            if (count != 0)               // record数组如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return false;
            }
        return true;
    }
}

语法补充--增强for循环

1    for (dataType variableName :collectionOrArray) {
2    // 循环体
3}

这里的dataType应该是你期望从集合或数组中取出的元素类型,variableName是你为每次迭代中取出的元素定义的变量名,而collectionOrArray是你想要遍历的数组或集合。

当执行这段代码时,循环会按照以下步骤进行:

  1. 初始化:循环开始前,首先检查collectionOrArray是否为空。如果是空的,循环将不会执行任何迭代并直接结束。

  2. 获取下一个元素:在每次迭代开始时,循环会从collectionOrArray中获取下一个元素,并将其赋值给variableName

  3. 执行循环体:一旦元素被赋值,循环体内的代码就会被执行。你可以在循环体内对元素进行任何操作,比如打印、修改等。

  4. 检查终止条件:在执行完一次循环体后,循环会检查是否还有更多的元素可供迭代。如果没有更多元素,循环结束;如果有,回到步骤2继续下一次迭代。

349. 两个数组的交集 

import java.util.HashSet;
import java.util.Set;

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        if (nums1 == null || nums1.length == 0 || nums2 == null || nums2.length == 0) {
            return new int[0];
        }
        Set<Integer> set1 = new HashSet<>();
        Set<Integer> resSet = new HashSet<>();
        //遍历数组1
        for (int i : nums1) {
            set1.add(i);
        }
        //遍历数组2的过程中判断哈希表中是否存在该元素
        for (int i : nums2) {
            if (set1.contains(i)) {
                resSet.add(i);
            }
        }
      
        //方法1:将结果集合转为数组

        return resSet.stream().mapToInt(x -> x).toArray();
        
        //方法2:另外申请一个数组存放setRes中的元素,最后返回数组
        int[] arr = new int[resSet.size()];
        int j = 0;
        for(int i : resSet){
            arr[j++] = i;
        }
        
        return arr;
    }
}

202. 快乐数

class Solution {
    public boolean isHappy(int n) {
        Set<Integer> record = new HashSet<>();
        while (n != 1 && !record.contains(n)) {
            record.add(n);
            n = getNextNumber(n);
        }
        return n == 1;
    }

    private int getNextNumber(int n) {
        int res = 0;
        //各个位上数的操作
        while (n > 0) {
            int temp = n % 10;
            res += temp * temp;
            n = n / 10;//推进循环
        }
        return res;
    }
}

1. 两数之和

思路

由于得到target的值组合会有多种,所以不能用简单的两层循环、

先遍历一遍数组,同时判断该数值是否之前出现过,还有与其相匹配的值是否遍历过,位置在哪

需要存储元素的值和下标,所以要用Map

那值和下标谁是key、谁是value

这时就要想清楚查找的是谁,在Java的HashMap类中,我们可以使用 get(key) 方法来获取 key 对应的 value,由题意可知应该是通过知道符合匹配条件的值,来找到对应下标,所以key是值,value是下标

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res = new int[2];
    if(nums == null || nums.length == 0){
        return res;
    }
    Map<Integer, Integer> map = new HashMap<>();
    for(int i = 0; i < nums.length; i++){
        int temp = target - nums[i];   // 遍历当前元素,并在map中寻找是否有匹配的key
        if(map.containsKey(temp)){
            res[1] = i;
            res[0] = map.get(temp);
            break;
        }
        map.put(nums[i], i);    // 如果没找到匹配对,就把访问过的元素和下标加入到map中
    }
    return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值