算法题型:映射(Map)

目录

一、leetcode 290. 单词规律

二、leetcode 205. 同构字符串

三、leetcode 451. 根据字符出现频率排序

四、leetcode 219. 存在重复元素 II

五、 leetcode 220. 存在重复元素 III

六、 leetcode 49. 字母异位词分组

七、leetcode347:Top K Frequent Elements

八、350:Intersection-of-Two-Arrays(II)


 

一、leetcode 290. 单词规律

1.题目描述

给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。

这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。

示例1:

输入: pattern = "abba", str = "dog cat cat dog"
输出: true

示例 2:

输入:pattern = "abba", str = "dog cat cat fish"
输出: false

示例 3:

输入: pattern = "aaaa", str = "dog cat cat dog"
输出: false

示例 4:

输入: pattern = "abba", str = "dog dog dog dog"
输出: false

2.题目分析:

采用两个Map,值都存储位置信息index,
其中Map1的key为字符,Map2的key为字符串。
通过put和get方法来进行添加和查询位置,以判断是否符合相同的规则。

3.代码:

public class Solution290 {
    public boolean wordPattern(String pattern, String str) {
        String[] strings = str.split(" ");
        if(strings.length!=pattern.length())return false;
        Map<Character,Integer> map1 = new HashMap<>();
        Map<String,Integer> map2 = new HashMap<>();
        for(int i=0;i<strings.length;i++){
            if (!map1.containsKey(pattern.charAt(i))) {
                map1.put(pattern.charAt(i), i);
            }
            if (!map2.containsKey(strings[i])) {
                map2.put(strings[i], i);
            }
            int a=map1.get(pattern.charAt(i));
            int b=map2.get(strings[i]);
            if(a!=b){
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        String pattern= "abba";
        String str="dog cat cat fish";
        Solution290 solution290 = new Solution290();
        boolean result=solution290.wordPattern(pattern,str);
        System.out.println(result);
    }
}

二、leetcode 205. 同构字符串

难度简单

1.题目描述

给定两个字符串 和 t,判断它们是否是同构的。

如果 中的字符可以被替换得到 ,那么这两个字符串是同构的。

所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。

示例 1:

输入: s = "egg", t = "add"
输出: true

示例 2:

输入: s = "foo", t = "bar"
输出: false

示例 3:

输入: s = "paper", t = "title"
输出: true

2.分析:同上一题类似

class Solution {
   public boolean isIsomorphic(String s, String t) {
        char [] strings1 = s.toCharArray();
        char [] strings2 = t.toCharArray();
        if(strings1.length!=strings2.length)return false;
        Map<Character,Integer> map1 = new HashMap<>();
        Map<Character,Integer> map2 = new HashMap<>();
        for(int i=0;i<strings1.length;i++){
            if (!map1.containsKey(strings1[i])) {
                map1.put(strings1[i], i);
            }
            if (!map2.containsKey(strings2[i])) {
                map2.put(strings2[i], i);
            }
            int a=map1.get(strings1[i]);
            int b=map2.get(strings2[i]);
            if(a!=b){
                return false;
            }
        }
        return true;
    }
}


 

三、leetcode 451. 根据字符出现频率排序

难度中等

1.题目描述

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

示例 1:

输入:
"tree"

输出:
"eert"

解释:
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。

示例 2:

输入:
"cccaaa"

输出:
"cccaaa"

解释:
'c'和'a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。

示例 3:

输入:
"Aabb"

输出:
"bbAa"

解释:
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A'和'a'被认为是两种不同的字符。

2.分析 

1.使用一个数组存储结果,下标代表字符的ASCII码,值存储pair

2.定义Pair类,包含频率和字符,两个元素

3.自定义Conparator,按照频率从大到小排序

package IMUHERO;

import java.util.Arrays;
import java.util.Comparator;

public class Solution451{
    public String frequencySort(String s) {
        Pair [] arr=new Pair[256];//定义一个数组,下标代表字符下标,值存储pair
        //初始化数组
        for (int i=0;i<256;i++){
            arr[i]=new Pair(0,(char)i);
        }
        //增加指定字符的频率
        for (int j=0;j<s.length();j++){
            arr[s.charAt(j)].fre++;
        }
        //频率高的往前排
        Arrays.sort(arr,new myCompare());
        StringBuffer str=new StringBuffer();
        for (int k=0;k<s.length();k++){
            if (arr[k].fre==0)break;
            //输出Pair中存储的所有字符
            while (arr[k].fre!=0) {
                str.append(arr[k].c);
                arr[k].fre--;
            }
        }
        return str.toString();
    }
}

//自定义Comparator排序规则是按照频率,从大到小
class myCompare implements Comparator<Pair> {
    @Override
    public int compare(Pair o1, Pair o2) {
        return o2.fre-o1.fre;
    }
}
//自定义封装类,用于存储频率和字符
class Pair{
    public int fre;
    public char c;
    Pair(int fre,char c){
        this.fre=fre;
        this.c=c;
    }
}

四、leetcode 219. 存在重复元素 II

难度简单

1.题目描述

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的绝对值最大为 k

示例 1:

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

示例 2:

输入: nums = [1,0,1,1], k = 1
输出: true

示例 3:

输入: nums = [1,2,3,1,2,3], k = 2
输出: false

2.分析

1.使用map存储下标和值

2.先判断值是否相等、再判断下标间距是否<=k,即可得出正确结果 

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

五、 leetcode 220. 存在重复元素 III

桶排序!!!

难度中等

1.题目描述

给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ

示例 1:

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

示例 2:

输入: nums = [1,0,1,1], k = 1, t = 2
输出: true

示例 3:

输入: nums = [1,5,9,1,5,9], k = 2, t = 3
输出: false

2.分析:使用桶排序

public class Solution220 {
    // Get the ID of the bucket from element value x and bucket width w
    // In Java, `-3 / 5 = 0` and but we need `-3 / 5 = -1`.
    private long getID(long x, long w) {
        return x < 0 ? (x + 1) / w - 1 : x / w;
    }

    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
        if (t < 0) return false;
        Map<Long, Long> d = new HashMap<>();
        long w = (long)t + 1;
        for (int i = 0; i < nums.length; ++i) {
            long m = getID(nums[i], w);
            // check if bucket m is empty, each bucket may contain at most one element
            if (d.containsKey(m))
                return true;
            // check the nei***or buckets for almost duplicate
            if (d.containsKey(m - 1) && Math.abs(nums[i] - d.get(m - 1)) < w)
                return true;
            if (d.containsKey(m + 1) && Math.abs(nums[i] - d.get(m + 1)) < w)
                return true;
            // now bucket m is empty and no almost duplicate in nei***or buckets
            d.put(m, (long)nums[i]);
            if (i >= k) d.remove(getID(nums[i - k], w));
        }
        return false;
    }
}

六、 leetcode 49. 字母异位词分组

难度中等

1.题目描述

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

2.分析

1.对字符串进行内部排序,这样异位词的KEY就会相同;

2.将相同KEY的字符串存储进一个MAP中,键为字符串,值为一个字符串链表

3.最后将MAP的VALUE:所有的链表放进二维List中,并作为结果返回

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {

        HashMap<String,List<String>> map = new HashMap<>();
        for (String s:strs){
            char [] c = s.toCharArray();
            Arrays.sort(c);
            String key = String.valueOf(c);
            if (!map.containsKey(key))map.put(key,new LinkedList<>());
            map.get(key).add(s);
        }
        List<List<String>> ret = new LinkedList(map.values());
        return ret;
    }
}

七、leetcode347:Top K Frequent Elements

一、题目要求:
347. 前K个高频元素

给定一个非空的整数数组,返回其中出现频率前 高的元素。

示例 1:

  1. 输入: nums = [1,1,1,2,2,3], k = 2

  2. 输出: [1,2]

示例 2:

  1. 输入: nums = [1], k = 1

  2. 输出: [1]

说明:

  • 你可以假设给定的 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
  • 你的算法的时间复杂度必须优于 O(n log n) , 是数组的大小。

二、简单分析

1.本题可以基于映射(map)实现对不同数据出现频次的存储;

2.实现一个最小堆的优先队列,将前K个优先级较高的元素存入优先队列,小于第K个元素的出队;

3.将优先队列中k个元素的数据存入LinkedlList中,提交给leetcode,即可完成任务!

三、代码实现

package IMUHERO;
/// 347. Top K Frequent Elements
/// https://leetcode.com/problems/top-k-frequent-elements/description/
import java.util.*;
 
public class Solution2 {
 
    private class Freq{
        public int e,freq;
        public Freq(int e ,int freq){
            this.e=e;
            this.freq=freq;
        }
    }
 
    private class FreqComparetor implements Comparator<Freq>{
        @Override
        public int compare(Freq a,Freq b){
                return a.freq-b.freq;
        }
    }
 
    public List<Integer> topKFrequent(int[] nums, int k) {
        TreeMap<Integer,Integer> map=new TreeMap<>();
        for (int num:nums){
            if (map.containsKey(num)){
                map.put(num,map.get(num)+1);
            }
            else{
                map.put(num,1);
            }
        }
 
        PriorityQueue<Freq> pQ=new PriorityQueue<>(new FreqComparetor());
        for (int key:map.keySet()){
            if (pQ.size()<k){
                pQ.add(new Freq(key,map.get(key)));
            }
            else if (map.get(key)>pQ.peek().freq){
                pQ.remove();
                pQ.add(new Freq(key,map.get(key)));
            }
        }
 
        LinkedList<Integer> res=new LinkedList<>();
        while (!pQ.isEmpty()){
            res.add(pQ.remove().e);
        }
        return res;
 
    }
 
   
}
 

八、350:Intersection-of-Two-Arrays(II)

一、题目

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

  1. 输入: nums1 = [1,2,2,1], nums2 = [2,2]

  2. 输出: [2,2]

示例 2:

  1. 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]

  2. 输出: [4,9]

说明:

  • 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
  • 我们可以不考虑输出结果的顺序。

进阶:

  • 如果给定的数组已经排好序呢?你将如何优化你的算法?
  • 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
  • 如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

二、代码

package IMUHERO;
import java.util.TreeMap;
import java.util.ArrayList;
class Solution {
    public int[] intersect(int[] nums1, int[] nums2) {
        TreeMap<Integer,Integer>treeMap=new TreeMap<>();
        for (int num:nums1){
            if (!treeMap.containsKey(num)) {
                treeMap.put(num,1);
            }
            else {
                treeMap.put(num,treeMap.get(num)+1);
            }
        }
        ArrayList<Integer>arrayList=new ArrayList<>();
        for (int num:nums2){
            if (treeMap.containsKey(num)){
                arrayList.add(num);
                treeMap.put(num,treeMap.get(num)-1);
                if (treeMap.get(num)==0)treeMap.remove(num);
            }
        }
        int [] reArr= new int[arrayList.size()];
        for (int i=0;i<arrayList.size();i++){
            reArr[i]=arrayList.get(i);
        }
        return reArr;
 
    }
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IMUHERO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值