亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

哈希表在算法題目中的實際應用詳解(Java)

 更新時間:2024年03月25日 09:05:26   作者:楠枬  
散列表(Hash?table,也叫哈希表)是根據關鍵碼值(Key?value)而直接進行訪問的數據結構,下面這篇文章主要給大家介紹了關于哈希表在算法題目中的實際應用,文中介紹的方法是Java,需要的朋友可以參考下

前言

在本篇文章中,我們重點講解哈希表在算法題目中的應用,不會涉及到太多哈希表的概念、原理等知識

首先,我們先來簡單回顧哈希表

哈希表知識回顧

哈希表是什么?

哈希表 是一種數據結構,用于存儲鍵值對。通過將鍵轉換為索引來實現快速的數據訪問。具體而言,哈希表使用一個哈希函數將鍵映射到一個特定的索引,然后將值存儲在該索引位置上。這樣,在查找、插入或刪除元素時,可以通過哈希函數直接計算出元素應該存儲或者所在的位置,從而實現高效的數據操作。哈希表的查詢、插入和刪除操作的時間復雜度通常為O(1)。簡而言之,哈希表是存儲數據的容器,是一種非常高效的數據結構

哈希表有什么作用?

 哈希表主要用于快速存儲、查找和刪除數據,在解決問題時,通常用于快速查找某個元素

什么時候使用哈希表?

(1)當我們需要 快速查找特定元素、 頻繁查找某一個元素 及 確定一個集合中是否存在重復元素 時,可以使用哈希表來存儲已經訪問過的元素,從而實現快速查找和查重

(2)當需要統(tǒng)計數據中各個元素出現的次數,可以使用哈希表來存儲元素及其對應的計數值,快速實現統(tǒng)計和計數

(3)當需要建立兩個數據集之間的映射關系時,可以使用哈希表來實現映射

怎么使用哈希表?

(1)使用容器,在解決算法問題時,我們常使用的哈希表容器有兩種:HashMap 和 HashSet

(2)使用數組模擬簡易哈希表,例如,在數據范圍很小的時候,我們可以考慮使用int類型的數組來模擬哈希表

接下來,我們以一些練習來進一步掌握哈希表在算法題目中的應用

練習1:存在重復元素

題目鏈接:

217. 存在重復元素 - 力扣(LeetCode)

題目描述:

給你一個整數數組 nums 。如果任一值在數組中出現 至少兩次 ,返回 true ;如果數組中每個元素互不相同,返回 false 。

示例 1:

<strong>輸入:</strong>nums = [1,2,3,1]
<strong>輸出:</strong>true

示例 2:

<strong>輸入:</strong>nums = [1,2,3,4]
<strong>輸出:</strong>false

示例 3:

<strong>輸入:</strong>nums = [1,1,1,3,3,4,3,2,4,2]
<strong>輸出:</strong>true

提示:

  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109

思路分析:

 首先我們來分析題目,在整數數組中,若有一個數在數組中出現了兩次以上,則返回true,否之,返回false。我們很容易想到暴力解法,即 固定一個元素,然后向后遍歷,觀察是否有與其相同的元素,其時間復雜度為 O(N ^ 2),因此,當測試數據量較大時,會超出時間限制

在暴力枚舉時,由于我們每次固定一個元素再向后遍歷,因此,很多不符合的元素被重復遍歷,為了不遍歷這些不符合的元素,我們可以考慮使用哈希表來存放這些元素。對于數組中的每個元素,我們將其插入到哈希表中,若在插入前該元素已經存在于哈希表中,則說明存在重復元素

代碼實現:

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> hash = new HashSet<>();
        for(int i = 0; i < nums.length; i++{
            if(hash.contains(nums[i])){
                return true;
            }else{
                hash.add(nums[i]);
            }
        }
        return false;
    }
}

練習2:存在重復元素II

題目鏈接:

219. 存在重復元素 II - 力扣(LeetCode)

題目描述:

給你一個整數數組 nums 和一個整數 k ,判斷數組中是否存在兩個 不同的索引 i 和 j ,滿足 nums[i] == nums[j] 且 abs(i - j) <= k 。如果存在,返回 true ;否則,返回 false 。

示例 1:

<strong>輸入:</strong>nums = [1,2,3,1], k = 3
<strong>輸出:</strong>true

示例 2:

<strong>輸入:</strong>nums = [1,0,1,1], k = 1
<strong>輸出:</strong>true

示例 3:

<strong>輸入:</strong>nums = [1,2,3,1,2,3], k = 2
<strong>輸出:</strong>false

提示:

  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • 0 <= k <= 105

思路分析:

 本題的解題思路與練習1類似,但不同的是:在找到兩個相同元素時,要判定這兩個元素的下標絕對值是否小于等于k。因此,我們既要保存數組元素,還要保存元素下標。

由于數組中同一個元素可能出現兩次以上,當判斷兩個相同元素的數組下標的差(abs(i - j))大于k時,要將哈希表中的下標更新為當前下標。例如:

代碼實現:

class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        Map<Integer, Integer> hash = new HashMap<>();
        for(int i = 0; i < nums.length; i++){
            if(hash.containsKey(nums[i]) && (i - hash.get(nums[i]) <= k)){
                return true;
            }else{
                hash.put(nums[i], i);
            }
        }
        return false;
    }
}

練習3:兩數之和

題目鏈接:

1. 兩數之和 - 力扣(LeetCode)

題目描述:

給定一個整數數組 nums 和一個整數目標值 target,請你在該數組中找出 和為目標值 target  的那 兩個 整數,并返回它們的數組下標。

你可以假設每種輸入只會對應一個答案。但是,數組中同一個元素在答案里不能重復出現。

你可以按任意順序返回答案。

示例 1:

<strong>輸入:</strong>nums = [2,7,11,15], target = 9
<strong>輸出:</strong>[0,1]
<strong>解釋:</strong>因為 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

<strong>輸入:</strong>nums = [3,2,4], target = 6
<strong>輸出:</strong>[1,2]

示例 3:

<strong>輸入:</strong>nums = [3,3], target = 6
<strong>輸出:</strong>[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只會存在一個有效答案

思路分析:

本題要求我們在整數數組中找到兩個元素,這兩個元素的和為target,本題與練習1的解題思路類似,我們可以使用哈希表來存放整數數組中的元素及其下標,在哈希表中尋找是否存在元素 target - nums[i],需要注意的是,若我們先將數組中所有元素和下標都存放在哈希表中,然后再遍歷數組,查找哈希表中是否存在元素 target - nums[i],此時可能會出現同一個元素在答案中重復出現的情況(例如:target = 8,nums = [1, 2, 4, 3],當前元素nums[2] = 4,由于數組中所有元素及下標已經放在哈希表中,因此此時元素4存在于哈希表中,但其下標與當前下標相同,即一個元素在答案中重復出現)

因此,若我們先將數組中所有元素和下標放入哈希表時,在查找哈希表中是否存在元素 target - nums[i]時,還需要判斷其下標是否與當前下標相同

我們還可以邊遍歷數組,邊向數組中存放元素,此時,哈希表中存放的元素為 nums[i]之前的元素,查找當前元素之前是否存在元素 = target - nums[i],這樣,就不需要對下標進行判斷了

代碼實現:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        for(int i = 1; i < nums.length; i++){
            for(int j = i - 1; j >= 0; j--){
                if(nums[i] + nums[j] == target){
                    return new int[] {i, j};
                }
            }
        }
        return null;
    }
}

練習4:判定是否互為字符重排

題目鏈接:

面試題 01.02. 判定是否互為字符重排 - 力扣(LeetCode)

題目描述:

給定兩個由小寫字母組成的字符串 s1 和 s2,請編寫一個程序,確定其中一個字符串的字符重新排列后,能否變成另一個字符串。

示例 1:

<strong>輸入:</strong> <code>s1</code> = "abc", <code>s2</code> = "bca"
<strong>輸出:</strong> true

示例 2:

<strong>輸入:</strong> <code>s1</code> = "abc", <code>s2</code> = "bad"
<strong>輸出:</strong> false

說明:

  • 0 <= len(s1) <= 100
  • 0 <= len(s2) <= 100

思路分析:

題目要求我們判斷字符串s1和s2是否 是s1中的字符重新排列后,變?yōu)閟2。若s1中的字符能夠重新排列成s2,則s1中的字符與s2中的字符相同。要想保證兩字符串字符相同,首先兩字符串的長度必須相同,因此,我們先判斷兩字符串長度是否相同,若相同,我們再來判斷其中字符是否都相同。

我們可以使用哈希表來保存字符及其出現的次數,先遍歷s1,保存其所有的字符及其出現的次數,再遍歷s2,若當前字符不在哈希表中,則兩字符串中存在不相同的字符,直接返回false;若當前字符在哈希表中,則次數 - 1,若次數 - 1 之后為 -1,則說明當前字符出現次數大于 s1中出現次數,兩字符串字符不完全相同,返回false。若完成遍歷,則說明兩字符串中的字符完全相同,返回true

由于兩個字符串中的字符都是由小寫字母構成的,因此,我們可以使用數組來模擬哈希表,創(chuàng)建一個大小為26的int類型數組,下標表示字符(例如 a 對應下標 0,b對應下標 1...)而元素表示字符的出現次數

代碼實現:

class Solution {
    public boolean CheckPermutation(String s1, String s2) {
        if(s1.length() != s2.length()) return false;//先判斷長度是否相同
        if(s1 == null) return true;//若兩字符串都為空,則直接返回true
        int[] hash = new int[26];//使用int數組模擬哈希表
        for(int i = 0; i < s1.length(); i++){//先遍歷s1,將字符及其出現次數存放在哈希表中
            hash[s1.charAt(i) - 'a']++;
        }
        for(int i = 0; i < s2.length(); i++){//再遍歷s2,判斷兩字符是否相同
           if(--hash[s2.charAt(i) - 'a'] < 0) return false; 
        }
        return true;
    }
}

練習5:字母異位詞分組

題目鏈接:

49. 字母異位詞分組 - 力扣(LeetCode)

題目描述:

給你一個字符串數組,請你將 字母異位詞 組合在一起。可以按任意順序返回結果列表。

字母異位詞 是由重新排列源單詞的所有字母得到的一個新單詞。

示例 1:

<strong>輸入:</strong> strs = <code>["eat", "tea", "tan", "ate", "nat", "bat"]</code>
<strong>輸出: </strong>[["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:

<strong>輸入:</strong> strs = <code>[""]</code>
<strong>輸出: </strong>[[""]]

示例 3:

<strong>輸入:</strong> strs = <code>["a"]</code>
<strong>輸出: </strong>[["a"]]

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 僅包含小寫字母

思路分析:

字母異位詞與 練習4 中的 字符重排 相同,即 兩個字符串中的所有字符相同。題目要求我們將所有 字母異位詞組合在一起,即將 所有字符相同的字符串放在一個集合中

首先,我們解決第一個問題:如何判斷字母異位詞?

在 練習4 中,我們使用數組模擬的哈希表來判斷兩個字符串是否互為字符重排,但在本題中,我們不能繼續(xù)使用這種方式來判斷字母異位詞,因為本題中存在許多組字母異位詞,若通過這種方式來判斷字母異位詞,則每次都需要遍歷不同組字母異位詞和當前字符串。在這里,我們可以考慮將字符串按照 ASCII碼值進行升序排列,(例如:eat 排列后 為 aet,tea排列后 為 aet)此時,只需要判斷排列后的字符串是否相同,即可判斷出兩個字符串是否為同一組字母異位詞

接下來,我們解決第二個問題:如何將字母異位詞組合在一起?

 哈希表可以統(tǒng)計數據中各個元素出現的次數,使用哈希表可以存儲元素及其對應的計數值,在這里,我們可以使用哈希表 存儲 排列后的字符串 及其 字母異位詞,即 key:存儲排列后的字符串,value:存儲 List,其中存放的元素類型為 String,這樣,就可以將字母異位詞存放在List中 

因此,我們只需要遍歷字符串數組,將其按照ASCII碼值進行升序排列,然后判斷排列后的字符串是否已經存在于哈希表中,若存在,則將 字母異位詞 放入List中;若不存在,則創(chuàng)建新的ArrayList

代碼實現:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> hash = new HashMap<>();
        for(String str: strs){
            char[] chs = str.toCharArray();
            Arrays.sort(chs);
            String key = new String(chs);
            List list = hash.getOrDefault(key, new ArrayList<String>());
            list.add(str);
            hash.put(key, list);
        }
        return new ArrayList<List<String>>(hash.values());
    }
}

總結 

到此這篇關于哈希表在算法題目中的實際應用的文章就介紹到這了,更多相關Java算法題中哈希表內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • spring boot 配置Filter過濾器的方法

    spring boot 配置Filter過濾器的方法

    本篇文章主要介紹了spring boot 配置Filter過濾器的方法,實例分析了spring boot 配置Filter過濾器的技巧,有興趣的可以了解一下。
    2017-03-03
  • java使用des加密解密示例分享

    java使用des加密解密示例分享

    java使用des加密解密示例,適合java語言的所有平臺,與.net等平臺的加密解密兼容
    2014-02-02
  • 如何通過??低曉O備網絡SDK進行Java二次開發(fā)攝像頭車牌識別詳解

    如何通過海康威視設備網絡SDK進行Java二次開發(fā)攝像頭車牌識別詳解

    這篇文章主要介紹了如何通過??低曉O備網絡SDK進行Java二次開發(fā)攝像頭車牌識別的相關資料,描述了如何使用海康威視設備網絡SDK進行車牌識別和圖片抓拍的開發(fā)流程,包括遇到的問題及其解決辦法,需要的朋友可以參考下
    2025-02-02
  • springboot項目打包發(fā)布部署的過程及jar和war的區(qū)別

    springboot項目打包發(fā)布部署的過程及jar和war的區(qū)別

    Spring Boot使用了內嵌容器,因此它的部署方式也變得非常簡單靈活,可以將Spring Boot項目打包成JAR包來獨立運行,Spring Boot項目既可以生成WAR包發(fā)布,也可以生成JAR包發(fā)布,那么它們有什么區(qū)別呢
    2022-11-11
  • Springboot詳解整合SpringSecurity實現全過程

    Springboot詳解整合SpringSecurity實現全過程

    Spring Security基于Spring開發(fā),項目中如果使用Springboot作為基礎,配合Spring Security做權限更加方便,而Shiro需要和Spring進行整合開發(fā)。因此作為spring全家桶中的Spring Security在java領域很常用
    2022-07-07
  • MyBatis中XML映射器的實現

    MyBatis中XML映射器的實現

    MyBatis的真正強大在于它的語句映射,映射器的XML文件就顯得相對簡單,本文主要介紹了MyBatis中XML映射器的實現,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • springboot項目中引入本地依賴jar包并打包到lib文件夾中

    springboot項目中引入本地依賴jar包并打包到lib文件夾中

    這篇文章主要介紹了springboot項目中引入本地依賴jar包,如何打包到lib文件夾中,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • Java使用AES加密和解密的實例詳解

    Java使用AES加密和解密的實例詳解

    這篇文章主要介紹了Java使用AES加密和解密的實例詳解的相關資料,需要的朋友可以參考下
    2017-07-07
  • springBoot快速訪問工程目錄下的靜態(tài)資源

    springBoot快速訪問工程目錄下的靜態(tài)資源

    springboot工程,是沒有webapp文件夾的,靜態(tài)文件放在src/main/resources/static文件夾下即可,模板文件放在src/main/resources/templates下,本文給大家介紹springBoot快速訪問工程目錄下的靜態(tài)資源的相關知識,一起看看吧
    2021-06-06
  • Feign如何使用protobuf的類作為參數調用

    Feign如何使用protobuf的類作為參數調用

    這篇文章主要介紹了Feign如何使用protobuf的類作為參數調用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論