IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 刷题:哈希表hash -> 正文阅读

[数据结构与算法]刷题:哈希表hash

DAY 6

补充哈希表写代码相关知识:
String s = “123”; char[] array = s.toCharArray() //123
toCharArray() 方法将字符串转换为字符数组。
Arrays.sort(数组名):为数组排序的操作。统一是由小到大
Arrays.equals(a,b): 在数组类型中,只比较内容相同; 换句话说,只要两个数组元素的顺序和内容都相同,则输出true。

String s = "123";
char[] array = s.toCharArray();
System.out.println(array);//123
int[] a = {1,2,3,4,5,8,11,44,-11};
int[] b= {8,11,44,-11};
Arrays.sort(a);// 给数组排序 -11 1 2 3 4 5 8 11 44
Arrays.toString(a);//返回数组的字符串格式 [-11, 1, 2, 3, 4, 5, 8, 11, 44]
System.out.println(Arrays.equals(a, b));//比较两个数组是否相等 false
System.out.println(Arrays.toString(a));//[-11, 1, 2, 3, 4, 5, 8, 11, 44]
System.out.println(Arrays.toString(b));//[8,11,44,-11]

补充ASCII相关知识

‘a’~'z’的ASCII是 97 - 122
‘A’~'Z’的ASCII是 65 - 90

补充HashMap的相关操作(java):

242.有效的字母异位词

题目要求:
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词
s与t中只有小写字母

输入: s = “anagram”, t = “nagaram”
输出: true

思路一:
既然要判断两个字符串中字符出现的次数是不是相同,因此如果将两个字符串按照从小到大的顺序排好,再去判断这两个字符串是不是完全相同,则就可以判断是不是s与t串是字母异位词了。

代码:

class Solution {
    public boolean isAnagram1(String s, String t) {
        char[] sChars = s.toCharArray();
        char[] tChars = t.toCharArray();
        Arrays.sort(sChars);//[a, a, a, g, m, n, r]
        Arrays.sort(tChars);// [a, a, a, g, m, n, r]
        return Arrays.equals(sChars, tChars); //true
    }
}

思路二:
定义一个record数组,记录的是两个char数组的ASCLL的差值 :
步骤:

1 定义一个数组记录 数组最大长度为26 因为26个字母 不会再超过26了
2 分别将这两个字符串的形式转换为char类型数组的形式
3 对arrayS进行遍历 record 下标就是记录s字符串中的字母的所在位置,出现一次就加一次。因此record[]其实就是记录这个字母在字符串中出现了几次;同样再次遍历T字符串,对record[]做–操作,如果最后record[]为空了 就说明这两个字符串字符出现的次数是相同的!!!
4 最后对hash数组进行遍历 record数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。

class Solution {
    public boolean isAnagram(String s, String t) {
    
        // 定义一个数组记录 数组最大长度为26 因为26个字母 不会再超过26了
        int[] record = new int[26];
      
        // 分别将这两个字符串的形式转换为char类型数组的形式
        char[] arrayS = s.toCharArray();
        char[] arrayT = t.toCharArray();
        // 对arrayS进行遍历  
        // record 下标就是记录s字符串中的字母的所在位置,出现一次就加一次。因此record[]其实就是记录这个字母在字符串中出现了几次。
        for(int i=0;i<arrayS.length;i++){
            record[arrayS[i]-'a']++;
        }
        // 再次遍历T字符串,对record[]做--操作,如果最后record[]为空了 就说明这两个字符串字符出现的次数是相同的!!!
        for(int i=0;i<arrayT.length;i++){
            record[arrayT[i]-'a']--;
        }
        
        // 最后对hash数组进行遍历
        //record数组如果有的元素不为零0,说明字符串s和t一定是谁多了字符或者谁少了字符,return false。
        for(int i=0;i<record.length;i++){
            if(record[i]!=0){
                return false;
            }
        }
        return true;
    }
}

补充思路二中的遍历操作:也可以直接用增强for循环进行遍历:

// 对字符串s进行遍历: 
for (char c : s.toCharArray()) {
     record[c - 'a'] ++;
}

思路三:
如果直接用java中的hsahmap来做,首先自己先去IDEA中去了解hashmap怎么新建怎么用,以上内容在博文开头回头补充;要知道hashmap是k-v存放的,因此我们可以根据字符串中出现的字符为key,出现的次数为value,然后再去比较:

class Solution {
    public boolean isAnagram(String s, String t) {
// k-v 对应的是
//a-3
//r-1
//g-1
//m-1
//n-1   
        char[] array = s.toCharArray();
        HashMap<Character, Integer> hashMap = new HashMap<>();

        char[] array2 = t.toCharArray();
        HashMap<Character, Integer> hashMap2 = new HashMap<>();


        for (int i = 0; i < array.length; i++) {
            hashMap.put(array[i],hashMap.getOrDefault(array[i],0)+1);
        }

        for (int i = 0; i < array2.length; i++) {
            hashMap2.put(array2[i],hashMap2.getOrDefault(array2[i],0)+1);
        }

        return hashMap.equals(hashMap2);
        
    }
    
}

上面写的不好 ,等会修改下,

class Solution {
    public boolean isAnagram(String s, String t) {

        HashMap<Character, Integer> hashMap = new HashMap<>();

        //遍历字符串s,对应key(字符)-value(出现次数)
        for (char c:s.toCharArray()) {
            hashMap.put(c, hashMap.getOrDefault(c, 0) + 1);
        }

        // 遍历字符串t,
        for (char ch : t.toCharArray()) {
            Integer value = hashMap.get(ch);//遍历t字符串得到的字符去字符串s中寻找,记下value;
            // 如果value为null:说明字符串t的字符在字符串s中并没有出现
            // 或者value<1 说明字符串t中的字符出现次数大于字符串s中这个字符出现的次数
            // 因此都不满足题目条件 返回false
            if(value == null || value<1) {
                return false;
            }else if(value>1){ // 如果value大于1 ,就不停的--;
                hashMap.put(ch,value-1);
            }else{// 如果value=1的时候,就移除这个key-value
                hashMap.remove(ch);
            }  
        }
        return hashMap.isEmpty();// 如果最后hashmap中无元素了,就是满足题目条件了      
    }
}

349 两个数组的交集

题目描述:
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

思路:
用到了HashSet,要去熟悉一下HashSet在java中的一些相关操作

代码:
自己AC的 做法 不是很好

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        // 定义一个set集合 用来放交集元素的
        Set<Integer> set = new HashSet<>();
        
        for (int i = 0; i < nums1.length; i++) {
            for (int j = 0; j < nums2.length; j++) {
                if (nums1[i] ==nums2[j]){
                    set.add(nums1[i]);
                    break;
                }
            }
        }
        // 因为返回的是int[] 因此定义一个数组 数组的长度就是set集合的大小
        int[] resArr = new int[set.size()];
        int index = 0;
        //将结果几何转为数组
        for (int i : set) {
            resArr[index] = i;
            index++;
        }
        return resArr;
    }
}

**改进代码2 **

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 把数组1中的值存放在set1集合中
        for (int i : nums1) {
            set1.add(i);
        }
        //遍历数组2的过程中判断哈希表set1中是否存在该元素
        for (int i : nums2) {
            if (set1.contains(i)) {
                resSet.add(i);
            }
        }
        int[] resArr = new int[resSet.size()];
        int index = 0;
        //将结果几何转为数组
        for (int i : resSet) {
            resArr[index] = i;
            index++;
        }
        return resArr;
    }
}

202 快乐数

题目要求:

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1,那么这个数就是快乐数。如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

解题思路:
求余数.关于%的法则,当左边的绝对值小于右边的绝对值的时候,结果是左边!结果是: 1%10=1.

代码:【不太会,回头看】

class Solution {
    public boolean isHappy(int n) {
        // 用一个set集合装记录结果:
        Set<Integer> record = new HashSet<>();
        while (n != 1 && !record.contains(n)) {
            record.add(n);
            n = getNextNumber(n);
        }
        return n == 1;
    }

   
    private static int getNextNumber(int n) {
        int res = 0;
        // 只要 n 是大于0 的数就不断地循环
        while (n > 0) {
            int temp = n % 10;
            res += temp * temp;
            n = n / 10;
        }
        return res;
    } 
}

1 两数之和

题目要求:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
输入:nums = [3,2,4], target = 6
输出:[1,2]
输入:nums = [3,3], target = 6
输出:[0,1]

思路1:
自己AC的 不好:
代码:

class Solution {
    public int[] twoSum(int[] nums, int target) {

        // 返回的答案 也是一个长度为2的数组
        int[] anwer= new int[2];
        for(int i=0;i<nums.length;i++){
            for(int j=i+1;j<nums.length;j++){
                if(nums[i]+nums[j]==target){
                    anwer[0]=i;
                    anwer[1]=j;
                    return anwer;
                }
            }
        }
        return anwer;
    }
}

改进:
思路2
本题呢,则要使用map,那么来看一下使用数组和set来做哈希法的局限。

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
    - set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。

此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。用了Map HashMap集合

代码:

public int[] twoSum(int[] nums, int target) {
     
    int[] res = new int[2];  //返回结果的数组 长度是2
    // 判断给出的nums数组 是不是空 返回结果也为空
    if(nums == null || nums.length == 0){
        return res;
    }
    
    // new 一个Map集合 key-vaule 都是整型
    Map<Integer, Integer> map = new HashMap<>();
    // 对nums数组进行遍历 nums = [2,7,11,15], target = 9
    for(int i = 0; i < nums.length; i++){  // 遍历[0,1,2,3]下标
        // temp = 9-nums[0]=9-2=7   temp = 9-7=2
        int temp = target - nums[i];
        // 判断是不是这个key在map中 
        if(map.containsKey(temp)){
            res[1] = i;
            res[0] = map.get(temp);
        }
        //key-value (2,0) i++-->i=1
        map.put(nums[i], i);
    }
    return res;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-22 21:39:02  更:2022-10-22 21:40:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:19:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码