6.哈希

一.宝石与石头
1.题目描述:
给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。
J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。

2.示例:
输入: J = "aA", S = "aAAbbbb"
输出: 3
S 和 J 最多含有50个字母。
J 中的字符不重复。

3.解:
(1)我的答案:

class Solution {
    public int numJewelsInStones(String jewels, String stones) {
        int nums=0;
        Set<Character> jewelSet = new HashSet<Character>();
        for (int i = 0;i<jewels.length();i++){
            jewelSet.add(jewels.charAt(i));
        }
        for (int i=0;i<stones.length();i++){
            if (jewelSet.contains(stones.charAt(i))){
                nums++;
            }
        }
        return nums;
    }
}

(2)网友答案:

class Solution {
    public int numJewelsInStones(String J, String S) {
        int len = J.length();
        int[] type = new int[256];
        for(int i = 0; i < len; i++){
            type[J.charAt(i)] = 1;
        }
        int ans = 0;
        len = S.length();
        for(int i = 0; i < len; i++){
            ans += type[S.charAt(i)];
        }
        return ans;
    }
}

4.总结:
常规的思路是哈希集合或者两个for循环遍历,总之这两种方案是不能及兼容时间复杂度又兼容空间复杂度的。但是网友的答案就很灵巧,利用了字符可以转换为int类型的原理,不仅时间复杂度小,空间复杂度也小。

二.存在重复元素
1.题目描述:
给定一个整数数组,判断是否存在重复元素。
如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。。

2.示例:
输入: [1,2,3,1]
输出: true

3.解:
(1)我的答案:

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

(2)网友答案:

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

        Set<Integer> data = new HashSet<>();

        for (int i = 0; i < nums.length; i++) {
            data.add(nums[i]);
        }
        if (data.size() == nums.length) {
            return false;
        }
        return true;
    }
class Solution {
    public boolean containsDuplicate(int[] nums) {
        //遇事不决先排序
        Arrays.sort(nums);
        int m = 0;
        for(int i = 1; i < nums.length; ++i){
            if(nums[i] == nums[m]){
                //存在重复元素
                return true;
            } else {
                ++m;
            }
        }
        //不存在
        return false;
    }
}

4.总结:我的方法思路是对的,正常的哈希集合,但是需要优化一下下,比如网友答案的第一个答案中,.add()方法本身就具有去重复的功能,这一点,第二个答案也体现了。所以不需要再去调用.contains()方法去判断是否包含当前元素了。另外最后一个答案的排序做法也很巧妙,排序之后,如果存在重复元素,那么一定存在相邻的两个元素的值相等。

三.存在重复元素ii
1.题目描述:
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

2.示例:
输入: nums = [1,2,3,1], k = 3
输出: true

3.解:

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

4.总结:
在这种情况下有两种方法:
(1)使用哈希map/哈希table,根据key找出value,key设置为值,value设置为数组的下标。
(2)这种方法利用了哈希集合的最独特的特点,即它的大小是可变的,可随意添加和删除指定元素。因此诞生了滑窗法,滑窗法顾名思义,滑块内的元素个数永远是固定大小的,先在末尾添加一个元素,再删除头部的元素,这样可以模拟滑块的前进操作。

四.存在重复元素iii
1.题目描述:
给你一个整数数组 nums 和两个整数 k 和 t 。请你判断是否存在 两个不同下标 i 和 j,使得 abs(nums[i] - nums[j]) <= t ,同时又满足 abs(i - j) <= k 。如果存在则返回 true,不存在返回 false。

2.示例:
输入:nums = [1,2,3,1], k = 3, t = 0
输出:true

3.解:
后面再做
4.总结:

五.变位词组
1.题目描述:
编写一种方法,对字符串数组进行排序,将所有变位词组合在一起。变位词是指字母相同,但排列不同的字符串。

2.示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]

3.解:
(1)我的答案:

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        HashMap<String, List<String>> hashMap = new HashMap<>();
        for (int i = 0; i < strs.length; i++) {
            char[] ele = strs[i].toCharArray();
            Arrays.sort(ele);
            if (!hashMap.containsKey(String.valueOf(ele))) hashMap.put(String.valueOf(ele), new ArrayList<>());
            hashMap.get(String.valueOf(ele)).add(strs[i]);
        }
        List<List<String>> res = new ArrayList<>(hashMap.values());
        return res;
    }
}

4.总结:
学到哈希的两个新用法,1.hash的value可以是集合,每次添加元素时,先判断有没有key,没有就创建一个键值对,然后用hash对象.get(key).add(element)即可。2.在创建ArrayList时候可以直接传值new ArrayList<>(value),value甚至可以是集合。

六.T9键盘
1.题目描述:
在老式手机上,用户通过数字键盘输入,手机将提供与这些数字相匹配的单词列表。每个数字映射到0至4个字母。给定一个数字序列,实现一个算法来返回匹配单词的列表。你会得到一张含有有效单词的列表。映射如下图所示:

图片说明

2.示例:
输入: num = "8733", words = ["tree", "used"]
输出: ["tree", "used"]

输入: num = "2", words = ["a", "b", "c", "d"]
输出: ["a", "b", "c"]

num.length <= 1000
words.length <= 500
words[i].length == num.length
num中不会出现 0, 1 这两个数字

3.解:

class Solution {
    public List<String> getValidT9Words(String num, String[] words) {
        HashMap<Character, Character> tire = new HashMap<>(26);
        tire.put('a', '2');
        tire.put('b', '2');
        tire.put('c', '2');
        tire.put('d', '3');
        tire.put('e', '3');
        tire.put('f', '3');
        tire.put('g', '4');
        tire.put('h', '4');
        tire.put('i', '4');
        tire.put('j', '5');
        tire.put('k', '5');
        tire.put('l', '5');
        tire.put('m', '6');
        tire.put('n', '6');
        tire.put('o', '6');
        tire.put('p', '7');
        tire.put('q', '7');
        tire.put('r', '7');
        tire.put('s', '7');
        tire.put('t', '8');
        tire.put('u', '8');
        tire.put('v', '8');
        tire.put('w', '9');
        tire.put('x', '9');
        tire.put('y', '9');
        tire.put('z', '9');

        List<String> res = new ArrayList<>();

        for (String str : words) {
            boolean tip = true;
            for (int i = 0; i < str.length(); i++) {
                if (num.charAt(i) != tire.get(str.charAt(i))) {
                    tip = false;
                    break;
                }
            }
            if (tip) res.add(str);
        }

        return res;
    }
}

4.总结
属于暴力解法了

全部评论

相关推荐

11-28 16:00
已编辑
武汉理工大学 Java
想干测开的tomca...:这份简历是“短期项目硬堆中大型系统技术”的“技术炫技式造假模板”,槽点密集到能当反面教材: ### 1. 「项目时长」和「技术密度」严重脱节,造假痕迹焊死在简历上 两个项目时长分别是**3个月、2个月**,但堆了Spring AI、Elasticsearch、MinIO、Kafka、ShardingSphere、Docker、Sentinel等近20个中大型项目才用的技术——正常情况下,光把这些中间件的文档看完+环境搭好,3个月都不够,更别说实现“AI多轮对话、分库分表、RBAC权限、大模型调用”这些功能。 说白了:你这不是“做项目”,是把“后端技术栈清单”往项目里硬塞,明摆着“只调用了API,没碰过核心逻辑”。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务