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){ TreeSetrecord = new TreeSet (); for(int num:nums1) record.add(num); TreeSet resultSet = new TreeSet (); 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 hashSet = new HashSet<>(); for(int num:nums1) hashSet.add(num); HashSet 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){ TreeMaptreeMap = new TreeMap<>(); for(int num:nums1){ if(treeMap.containsKey(num)) treeMap.put(num, treeMap.get(num)+1); else treeMap.put(num, 1); } ArrayList 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 record = new HashMap (); for(int num: nums1) if(!record.containsKey(num)) record.put(num, 1); else record.put(num, record.get(num) + 1); ArrayList result = new ArrayList (); 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; HashSethashSet = new HashSet<>(); for(int i=0;i for(int i=0;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){ HashSethashSet = 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 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; HashMaphashMap = new HashMap<>(); for(int i=0;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; HashMaphashMap = new HashMap<>(); for(int i=0;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) { TreeMaptreeMap = new TreeMap<>(); for(int i=0;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 > list = new ArrayList<>(treeMap.entrySet()); Collections.sort(list, new Comparator >() { @Override public int compare(Map.Entry o1, Map.Entry o2) { return o2.getValue()-o1.getValue(); } }); StringBuilder str = new StringBuilder(); for(Map.Entry 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)进行排序,再输出就好了。