哈希

哈希

哈希表(Hash Table)是一种常见的数据结构,提供高效的查找、插入和删除操作。

(一)HashMap

HashMap 是 Java 中基于哈希表实现的 Map 接口的一个具体实现

1. put(key, value) : 插入元素

  • 作用:将指定的键值对插入到哈希表中。如果键已存在,则更新其对应的值。

  • 时间复杂度:平均 O(1)

Map<String, Integer> map = new HashMap<>();
map.put("apple", 3);  // 键 "apple" 对应的值为 3
map.put("banana", 5); // 键 "banana" 对应的值为 5
map.put("apple", 4);  // 键 "apple" 已存在,更新值为 4

2. get(key) : 查找元素

  • 作用:根据给定的键返回对应的值。如果键不存在,返回 null
  • 时间复杂度:平均 O(1),最坏情况 O(n)(当发生大量哈希冲突时)。
Integer value = map.get("apple");  // 返回 4
Integer value2 = map.get("orange");  // 返回 null

3. containsKey(key) : 检查是否包含某个键

  • 作用:检查哈希表中是否包含指定的键。
  • 时间复杂度:O(1)
boolean contains = map.containsKey("apple");  // 返回 true
boolean contains2 = map.containsKey("orange");  // 返回 false

4. containsValue(value) : 检查是否包含某个值

  • 作用:检查哈希表中是否包含指定的值。

  • 时间复杂度:O(n)(需要遍历所有值)。

boolean containsValue = map.containsValue(4);  // 返回 true

5. remove(key) : 删除指定键的元素

  • 作用:从哈希表中删除指定键值对。
  • 时间复杂度:平均 O(1),最坏情况下 O(n)。
map.remove("apple");  // 删除键 "apple" 及其对应的值

6. size() : 获取哈希表大小

  • 作用:返回哈希表中键值对的数量。

  • 时间复杂度:O(1)

int size = map.size();  // 返回哈希表中键值对的数量

7. isEmpty() : 检查哈希表是否为空

  • 作用:检查哈希表是否为空。如果没有元素,返回 true

  • 时间复杂度:O(1)

boolean isEmpty = map.isEmpty();  // 返回 true 如果哈希表为空

8. clear() : 清空哈希表

  • 作用:删除哈希表中的所有元素。

  • 时间复杂度:O(n),需要删除所有元素。

map.clear();  // 清空哈希表中的所有键值对

9. keySet() : 获取所有键的集合

  • 作用:返回哈希表中所有键的集合。

  • 时间复杂度:O(n)

Set<String> keys = map.keySet();  // 返回所有键的集合

10. values() : 获取所有值的集合

  • 作用:返回哈希表中所有值的集合。

  • 时间复杂度:O(n)

Collection<Integer> values = map.values();  // 返回所有值的集合

11.getOrDefault(key, defaultValue) : 获取键的值或默认值

  • 作用:根据给定的键返回值。如果键不存在,返回指定的默认值。

  • 时间复杂度:O(1)

Integer value = map.getOrDefault("apple", 0);  // 返回 4
Integer value2 = map.getOrDefault("orange", 0);  // 返回 0 (默认值)

12.putIfAbsent(key, value) : 如果键不存在,则插入键值对

  • 作用:只有当指定的键不存在时,才插入新的键值对。若键已存在,则不会修改值。

  • 时间复杂度:O(1)

map.putIfAbsent("apple", 3);  // 如果 "apple" 不存在,则插入,否则不做任何操作

13.replace(key, oldValue, newValue) : 替换键对应的值(只有值匹配时替换)

  • 作用:只有当指定的键对应的值为 oldValue 时,才会用 newValue 替换原值。

  • 时间复杂度:O(1)

map.replace("apple", 4, 10);  // 如果 "apple" 的值是 4,则将其替换为 10

(二)HashSet

HashSet 是 Java 中基于哈希表实现的 Set 接口的一个具体实现类。HashSet 用于存储不重复的元素,且不保证元素的顺序。

1. add(E e) : 添加元素

  • 作用:将指定的元素添加到 HashSet 中。如果元素已存在,则不添加。
  • 返回值:如果元素成功添加,返回 true;如果元素已存在,则返回 false
  • 时间复杂度:平均 O(1),最坏情况下 O(n)(当发生大量冲突时)。
HashSet<String> set = new HashSet<>();
set.add("apple");  // 返回 true
set.add("banana"); // 返回 true
set.add("apple");  // 返回 false,因为 "apple" 已经存在

2. remove(Object o) : 删除元素

  • 作用:从 HashSet 中删除指定的元素。如果元素存在,则删除并返回 true,否则返回 false

  • 返回值true 表示元素成功删除,false 表示元素不存在。

  • 时间复杂度:平均 O(1),最坏情况下 O(n)(当发生大量冲突时)。

set.remove("banana");  // 返回 true
set.remove("orange");  // 返回 false,因为 "orange" 不存在

3.contains(Object o) : 判断是否包含元素

  • 作用:检查 HashSet 中是否包含指定的元素。

  • 返回值:如果集合中包含指定的元素,返回 true;否则返回 false

  • 时间复杂度:平均 O(1),最坏情况下 O(n)(当发生大量冲突时)。

boolean hasApple = set.contains("apple");  // 返回 true
boolean hasOrange = set.contains("orange");  // 返回 false

4. size() : 获取集合大小

  • 作用:返回 HashSet 中元素的数量。
  • 时间复杂度:O(1)
int size = set.size();  // 返回集合中元素的个数

5. isEmpty() - 判断集合是否为空

  • 作用:检查 HashSet 是否为空。
  • 返回值:如果集合为空,返回 true;否则返回 false
  • 时间复杂度:O(1)
boolean isEmpty = set.isEmpty();  // 返回 true 如果集合为空

6. clear() - 清空集合

  • 作用:删除 HashSet 中的所有元素。
  • 时间复杂度:O(n),需要删除所有元素。
set.clear();  // 清空集合中的所有元素

Leetcode相关题目总结

1. 两数之和

import java.util.ArrayList;

class Solution {

    public int[] twoSum(int[] nums, int target) {
        //1.创建一个哈希表,用来存储已遍历的元素及其索引(key:元素的值-----value:元素的索引)
        Map <Integer,Integer> hastable=new HashMap <Integer,Integer>();

        //2.遍历数组中的每个元素
        for(int i=0;i<nums.length;i++){
            //计算当前元素需要的配对值
            int aim=target-nums[i];
            //判断该配对值是否已经在哈希表中出现过
            if(hastable.containsKey(aim)){       // 如果存在,说明找到了两个数,它们的和为target
                //返回配对值的下标和当前元素的下标
                return new int[]{i,hastable.get(aim)};
            }
            //如果没有找到,记录当前元素的值及其索引
            hastable.put(nums[i],i);
        }

        //3.如果遍历完数组没有找到符合条件的两个数,返回空数组
        return new int[0];
    }
}

49. 字母异位词分组

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map <String,List<String>> map =new HashMap <String,List<String>>();

        for(String str:strs){
            //1.将String类型的字符串转换成字符数组
            char[] array=str.toCharArray();
            //2.调用Arrays类提供的sort()方法,对字符型数组进行排序
            Arrays.sort(array);
            //3.将排序后的字符数组转换回String类型
            String key=new String(array);
            //4.声明一个list,用于存放map中与key对应的value(即所有字母异位词)
            //根据给定的key查找对应的value。如果key存在,则返回与该key关联的value;如果key不存在,则返回默认值,即new ArrayList<String>()(一个新的空字符串列表)
            List<String> list = map.getOrDefault(key,new ArrayList<String>());
            //5.将当前处理的字符串也加入list
            list.add(str);
            //6.向list插入一个新的键值对(如果key已经存在,则更新其对应的value)
            map.put(key,list);
        }
        
        //将 map 中的所有值(即 List<String> 类型的集合)转换为一个 ArrayList 并返回
        return new ArrayList <List<String>>(map.values());
    }
}

128.最长连续序列

class Solution {
    public int longestConsecutive(int[] nums) {
        // Step 1: 将数组中的元素添加到一个 HashSet 中,去重。
        Set<Integer> num_set=new HashSet<Integer>();
        for(int num:nums){
            num_set.add(num);
        }

        // Step 2: 初始化最大连续序列长度。
        int longestStreak=0;

        // Step 3: 遍历 HashSet 中的每个元素。
        for(int num:num_set){

            //判断当前数字是否**可能**是一个最长连续序列的起点
            //(如果 num-1 不在集合中,说明 num 是一个新序列的起点)
            if(!num_set.contains(num-1)){
                int currentNum=num;
                int currentStreak=1;

                //向右扩展序列,直到没有连续数字
                while(num_set.contains(currentNum+1)){
                    currentNum+=1;
                    currentStreak+=1;
                }

                //更新最大连续序列长度
                longestStreak = Math.max(longestStreak, currentStreak);
            }
        }
        // Step 4: 返回最长连续序列的长度
         return longestStreak;
    }
}
  • 时间复杂度是 O(n)

  • 为何使用 HashSet?

    • 频繁查找:最核心的操作是判断某个元素是否存在于集合中。使用 HashSet的 常数时间复杂度 O(1) 查找非常适合此类问题。每次判断是否存在 num-1num+1 时,查找操作非常频繁,选择 HashSet能够保证效率。
    • 去重:由于题目要求元素唯一,HashSet自带去重功能,这使得我们不需要手动判断是否插入重复元素。
posted @ 2025-12-25 17:24  juuddy  阅读(7)  评论(0)    收藏  举报