使用容器HashSet HashMap TreeSet TreeMap 解决的一系列问题

Set 集合 , Map 字典都是基本的接口,而HashSet , HashMap , TreeSet , TreeMap都是实现接口的容器。

Set : 集合, 集合内不能重复。它的两个实现类:

HashSet:HashSet的底层函数是用散列表写的,它的查找,删除,增加,修改的时间复杂度都是O(1),对于一些简单的问题,使用HashSet是一个非常快速而有效的方法,但是它的缺点在于,HashSet是没有顺序的,当我们需要用它来解决一些需要顺序输出的问题时,就不是那么好用了。

TreeSet : TreeSet的底层函数是用平衡树(AVL)写的,准确的说是用红黑树写的,这让它的增删改查操作的时间复杂度都是O(logn),速度相对HashSet来说要慢一些,而它的优点是,TreeSet会对它存储的数据进行排序,也可以自己修改排序规则,所以当我们解决一些复杂一点的问题时,我们可以用TreeSet。

Map : 字典 , 字典存储的是key - Value,即是键值对,键不可以重复。它的两个实现类:

HashMap:HashMap的底层函数一样使用散列表写的,一样没有顺序。

TreeMap:TreeMap的底层函数一样是用红黑树写的,TreeMap会对键进行排序,而不能对值进行排序。排序分为自然排序和定制排序,可以自己修改排序规则。

说了这么多,下面,先让我们来看一些几个简单的例子,来熟悉一下他们的用法:

我所使用的例子都是leetcode上的题目,大家感兴趣可以去leetcode上找一下

import java.util.HashSet;
import java.util.TreeSet;

/*
349. Intersection of Two Arrays
找到2个数组的公共元素
nums1 = [1,2,2,3] , nums2 = [2,2] , 公共元素为2
熟悉HashSet TreeSet容器类的使用方式
 */
public class Solution {
    public static int[] intersection(int[] nums1, int[] nums2){
        TreeSet<Integer> record = new TreeSet<Integer>();
        for(int num:nums1)
            record.add(num);
        TreeSet<Integer> resultSet = new TreeSet<Integer>();
        for( int num : nums2)
            if(record.contains(num))
                resultSet.add(num);
        int[] res = new int[resultSet.size()];
        int index=0;
        for(int num:resultSet)
            res[index++] = num;
        return res;
    }

    public static int[] intersection2(int[] nums1, int[] nums2){
        HashSet<Integer> hashSet = new HashSet<>();
        for(int num:nums1)
            hashSet.add(num);
        HashSet<Integer> hashSet1 = new HashSet<>();
        for(int num:nums2)
            if(hashSet.contains(num))
                hashSet1.add(num);
        int[] arr = new int[hashSet1.size()];
        int index = 0;
        for(int num:hashSet1)
            arr[index++] = num;
        return arr;
    }


    private static void printArr(int[] arr){
        for(int e: arr)
            System.out.print(e + " ");
        System.out.println();
    }

    public static void main(String[] args) {
        int[] nums1 = {1, 2, 2, 1};
        int[] nums2 = {2, 2};
        int[] res = intersection2(nums1, nums2);
        printArr(res);
    }
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TreeMap;

/*
350. Intersection of Two Arrays II
找到2个数组的交集
nums1 = [1,2,2,3] , nums2 = [2,2] 交集为[2,2]
熟悉HashMap TreeMap的使用方式
 */
public class Solution2 {
    public static int[] intersection(int[] nums1, int[] nums2){
        TreeMap<Integer,Integer> treeMap = new TreeMap<>();
        for(int num:nums1){
            if(treeMap.containsKey(num))
                treeMap.put(num, treeMap.get(num)+1);
            else
                treeMap.put(num, 1);
        }
        ArrayList<Integer> arrayList = new ArrayList<>();
        for(int num: nums2){
            if( treeMap.containsKey(num) && treeMap.get(num) > 0){
                arrayList.add(num);
                treeMap.put(num, treeMap.get(num)-1);
            }
        }
        int[] arr = new int[arrayList.size()];
        int index = 0;
        for(int num:arrayList)
            arr[index++] = num;
        return arr;
    }

    public int[] intersection2(int[] nums1, int[] nums2) {
        HashMap<Integer, Integer> record = new HashMap<Integer, Integer>();
        for(int num: nums1)
            if(!record.containsKey(num))
                record.put(num, 1);
            else
                record.put(num, record.get(num) + 1);
        ArrayList<Integer> result = new ArrayList<Integer>();
        for(int num: nums2)
            if(record.containsKey(num) && record.get(num) > 0){
                result.add(num);
                record.put(num, record.get(num) - 1);
            }
        int[] ret = new int[result.size()];
        int index = 0;
        for(Integer num: result)
            ret[index++] = num;
        return ret;
    }

    private static void printArr(int[] arr){
        for(int e: arr)
            System.out.print(e + " ");
        System.out.println();
    }

    public static void main(String[] args) {
        int[] nums1 = {1, 2, 2, 1};
        int[] nums2 = {2, 2};
        int[] arr = intersection(nums1, nums2);
        printArr(arr);
    }
}

这两个简单的例子都是用来熟悉基本用法的,再让我们看看其他的例子:

import java.util.HashSet;
//难度:**
/*
242 Valid Anagram
判断字符串t是否是字符串s变换顺序后的得到的结果
s = "anagram" t = "nagaram" true
s = "rat" t = "car" false
 */
public class ValidAnagram {
    public static boolean validAnagram(String s, String t){
        if(s.length()!=t.length())
            return false;
        HashSet<Character> hashSet = new HashSet<>();
        for(int i=0;i<s.length();i++)
            hashSet.add(s.charAt(i));
        for(int i=0;i<t.length();i++)
            hashSet.remove(t.charAt(i));
        if(hashSet.size()==0)
            return true;
        return false;
    }

    public static void main(String[] args) {
        String s = "anagram";
        String t = "nagaram";
        boolean flag = validAnagram(s,t);
        System.out.println(flag);
    }
}
//难度:**
/*
202 Happy Number
判断一个数是否是happy number。happy number 是指,一个数,将其替换为其各位数字的平方和,
重复这个过程,如果最终能得到1,这是happy number,如果这个过程陷入了一个不包含1的循环,
则不是happy number
19: 1^2 + 9^2 = 82 , 8^2 + 2^2 = 68 , 6^2 + 8^2 = 100 , 1^2 + 0^2 + 0^2 = 1
19: Happy Number
 */
public class HappyNumber {
    public static boolean happyNumber(int num){
        HashSet<Integer> hashSet = new HashSet<>();
        while(num!=1){
            if(hashSet.contains(num))
                return false;
            hashSet.add(num);
            num = sum(num);
        }
        return true;
    }

    public static int sum(int num){
        Vector<Integer> vec = new Vector<>();
        int sum = 0;
        while(num!=0){
            int n = num%10;
            sum+=(n*n);
            num = num/10;
        }
        return sum;
    }

    public static void main(String[] args) {
        int num = 19;
        boolean flag = happyNumber(num);
        if(flag)
            System.out.println("Happy Number!");
        else
            System.out.println("Not a Happy Number!");
    }
}
//难度:**
/*
205 Isomorphic Strings
判断2个字符串是否同构。如果我们能够寻找到一个字符集到字符集的映射,使得通过这个
字符集的映射,s可以转换为t,则称s和t同构
egg 和 add   true ,  foo 和 bar   false , paper 和 title  true
 */
public class IsomorphicStrings {
    public static boolean isomorphicStrings(String s, String t){
        if(s.length()!=t.length())
            return false;
        HashMap<Character, Character> hashMap = new HashMap<>();
        for(int i=0;i<s.length();i++){
            if(hashMap.containsKey(s.charAt(i))){
                if(!hashMap.get(s.charAt(i)).equals(t.charAt(i)))
                    return false;
                continue;
            }
            hashMap.put(s.charAt(i),t.charAt(i));
        }
        return true;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            String s = sc.next();
            String t = sc.next();
            boolean flag = isomorphicStrings(s, t);
            System.out.println(flag);
        }
    }
}
//难度:**
/*
290 Word Pattern
给出一个模式(pattern) 以及一个字符串,判断这个字符串是否符合模式
pattern = "abba" , str = "dog cat cat dog"  true
pattern = "abba" , str = "dog cat cat fish" false
 */
public class WordPattern {
    public static boolean wordPattern(String pattern, String str){
        String[] strings = str.split(" ");
        if(pattern.length()!=strings.length)
            return false;
        HashMap<Character, String> hashMap = new HashMap<>();
        for(int i=0;i<pattern.length();i++){
            char c = pattern.charAt(i);
            if(hashMap.containsKey(c)){
                if(!strings[i].equals(hashMap.get(c)))
                    return false;
                continue;
            }
            hashMap.put(c, strings[i]);
        }
        return true;
    }

    public static void main(String[] args) {
        String pattern = "abba";
        String str = "dog cat cat dog";
        boolean flag = wordPattern(pattern, str);
        System.out.println(flag);
    }
}
 
 
import java.util.*;

//难度:***
/*
451 Sort Characters By Frequency
给定一个字符串,按照字母出现频率倒序重组整个字符串
"tree" -> "eert"  "cccaaa"  -> "aaaccc"  "Aabb" -> "bbAa"
对于相同频次的字母,顺序任意。大小写敏感
 */
public class SortCharacters {
    public static String sortCharacters(String s) {
        TreeMap<Character, Integer> treeMap = new TreeMap<>();
        for(int i=0;i<s.length();i++){
            if(treeMap.containsKey(s.charAt(i)))
                treeMap.put(s.charAt(i), treeMap.get(s.charAt(i))+1);
            else
                treeMap.put(s.charAt(i), 1);
        }
        List<Map.Entry<Character, Integer>> list = new ArrayList<>(treeMap.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<Character, Integer>>() {
            @Override
            public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
                return o2.getValue()-o1.getValue();
            }
        });
        StringBuilder str = new StringBuilder();
        for(Map.Entry<Character, Integer> e:list){
            int v = e.getValue();
            while(v>0){
                str.append(e.getKey());
                v--;
            }
        }
        return str.toString();
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()){
            String s = sc.next();
            String str = sortCharacters(s);
            System.out.println(str);
        }
    }
}
 
 

这道题的思想不复杂,就是统计字母频率,然后根据频率输出,难点在怎么根据频率对键值对进行排序?

答案也很简单,就是通过list<>和Map.entry<>将键值对取出,重写比较函数,用Collections.sort(list)进行排序,再输出就好了。

猜你喜欢

转载自blog.csdn.net/qq_40006051/article/details/80723621