哈希表题目
无人机方阵
class Solution {
public int minimumSwitchingTimes(int[][] source, int[][] target) {
int[] tmp=new int[10001];
for(int i=0;i<source.length;++i){
for(int j=0;j<source[0].length;++j){
tmp[source[i][j]]++;
tmp[target[i][j]]--;
}
}
int ans=0;
for(Integer i:tmp){
if(i!=0){
ans+=Math.abs(i);
}
}
return (ans>>1);
}
}
找出 3 位偶数
class Solution {
public int[] findEvenNumbers(int[] digits) {
int[] base=new int[10];
for(Integer i:digits){
base[i]++;
}
Set<Integer>set=new HashSet<>();
for(int i=1;i<=9;++i){
if(base[i]==0)continue;
for(int j=0;j<=9;++j){
if(base[j]==0)continue;
else if(j==i&&base[j]<2)continue;
for(int k=0;k<9;k+=2){
if(base[k]==0)continue;
else if(k==i&&k==j){
if(base[k]<3)continue;
}
else if(k==i||k==j){
if(base[k]<2)continue;
}
set.add(i*100+j*10+k);
}
}
}
int[] ans=new int[set.size()];
int k=0;
for(Integer i:set){
ans[k++]=i;
}
Arrays.sort(ans);
return ans;
}
}
找到和最大的长度为 K 的子序列
class Solution {
public int[] maxSubsequence(int[] nums, int k) {
Map<Integer,Integer>map=new HashMap<>();
int[] tmp=new int[nums.length];
for(int i=0;i<nums.length;++i){
tmp[i]=nums[i];
}
Arrays.sort(nums);
int[] ans=new int[k];
//从 nums.length-k ~ nums.length-1 中遍历
int index=0;
for(int i=nums.length-k;i<nums.length;++i){
if(!map.containsKey(nums[i])){
List<Integer>list=new ArrayList<>();
list.add(i);
map.put(nums[i],1);
}else{
map.put(nums[i],map.get(nums[i])+1);
}
}
for(int i=0;i<nums.length;++i){
if(map.containsKey(tmp[i])&&map.get(tmp[i])>0){
ans[index++]=tmp[i];
map.put(tmp[i],map.get(tmp[i])-1);
}
}
return ans;
}
}
重新分配字符使所有字符串都相等
思路: 只要确保每个字符的数量是words数组长度的整数倍
class Solution {
public boolean makeEqual(String[] words) {
int[] chs=new int[26];
for(String s:words){
for(int i=0;i<s.length();++i){
chs[s.charAt(i)-'a']++;
}
}
for(Integer i:chs){
if(i%words.length!=0)return false;
}
return true;
}
}
验证外星语词典
class Solution {
private boolean isOk(Map<Character,Integer>map,String w1,String w2){
//w1是否<=w2
int i=0;
while(i<w1.length()&&i<w2.length()){
if(map.get(w1.charAt(i))>map.get(w2.charAt(i))){
return false;
}else if(map.get(w1.charAt(i))<map.get(w2.charAt(i))){
return true;
}
++i;
}
if(i<w1.length())return false;
return true;
}
public boolean isAlienSorted(String[] words, String order) {
Map<Character,Integer>map=new HashMap<>();
for(int i=0;i<order.length();++i){
map.put(order.charAt(i),i);
}
for(int i=0;i<words.length-1;++i){
if(!isOk(map,words[i],words[i+1])){
return false;
}
}
return true;
}
}
卡牌分组
class Solution {
private int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
public boolean hasGroupsSizeX(int[] deck) {
Map<Integer,Integer>map=new HashMap<>();
int x=0;
for(Integer i:deck){
if(!map.containsKey(i)){
map.put(i,1);
}else{
map.put(i,map.get(i)+1);
x=map.get(i);
}
}
for(Integer key:map.keySet()){
x=gcd(x,map.get(key));
if(x==1)return false;
}
return true;
}
}
亲密字符串
class Solution {
public boolean buddyStrings(String s, String goal) {
if(s.length()!=goal.length())return false;
int ans=0;
Set<Character>set=new HashSet<>();
char s1='a',s2='a';
char g1='a',g2='a';
for(int i=0;i<s.length();++i){
set.add(s.charAt(i));
if(s.charAt(i)!=goal.charAt(i)){
ans++;
if(ans>2)return false;
if(ans==1){
s1=s.charAt(i);
g1=goal.charAt(i);
}else{
s2=s.charAt(i);
g2=goal.charAt(i);
}
}
}
if(s.equals(goal))return set.size()!=s.length();
if(ans<2)return false;
return s1==g2&&s2==g1;
}
}
最常见的单词
class Solution {
public String mostCommonWord(String paragraph, String[] banned) {
String s=paragraph.toLowerCase();
List<String>list=new ArrayList<>();
int i=0;
while(i<s.length()){
if(s.charAt(i)>='a'&&s.charAt(i)<='z'){
int start=i;
while(i<s.length()&&s.charAt(i)>='a'&&s.charAt(i)<='z'){
i++;
}
list.add(s.substring(start,i));
}
++i;
}
Set<String>set=new HashSet<>();
for(String str:banned){
set.add(str);
}
Map<String,Integer>map=new HashMap<>();
for(String str:list){
if(str.charAt(str.length()-1)>='a'&&str.charAt(str.length()-1)<='z'){
}else{
str=str.substring(0,str.length()-1);
}
if(!map.containsKey(str)){
map.put(str,1);
}else{
map.put(str,map.get(str)+1);
}
}
String ans="";
int times=0;
for(String str:map.keySet()){
if(!set.contains(str)&&map.get(str)>times){
ans=str;
times=map.get(str);
}
}
return ans;
}
}
句子相似性
class Solution {
public boolean areSentencesSimilar(String[] sentence1, String[] sentence2, List<List<String>> similarPairs) {
if(sentence1.length!=sentence2.length)return false;
Set<String>set=new HashSet<>();
for(int i=0;i<similarPairs.size();++i){
set.add(similarPairs.get(i).get(0)+"_"+similarPairs.get(i).get(1));
}
for(int i=0;i<sentence1.length;++i){
if(sentence1[i].equals(sentence2[i]))continue;
else if(!set.contains(sentence1[i]+"_"+sentence2[i])&&!set.contains(sentence2[i]+"_"+sentence1[i]))return false;
}
return true;
}
}
设计哈希映射
class MyHashMap {
public class Node{
public int key;
public int val;
public Node(int k,int v){
key=k;
val=v;
}
}
private int base=377;
private LinkedList[] map;
public MyHashMap() {
map=new LinkedList[base];
for(int i=0;i<base;++i){
map[i]=new LinkedList<Node>();
}
}
public void put(int key, int value) {
int hashValue=hash(key);
if(!containsKey(key)){
map[hashValue].add(new Node(key,value));
}else{
for(int i=0;i<map[hashValue].size();++i){
if(((Node)(map[hashValue].get(i))).key==key){
((Node)(map[hashValue].get(i))).val=value;
break;
}
}
}
}
public int get(int key) {
if(containsKey(key)){
int hashValue=hash(key);
for(int i=0;i<map[hashValue].size();++i){
if(((Node)(map[hashValue].get(i))).key==key){
return ((Node)(map[hashValue].get(i))).val;
}
}
}
return -1;
}
public void remove(int key) {
if(!containsKey(key))return ;
int hashValue=hash(key);
for(int i=0;i<map[hashValue].size();++i){
if(((Node)(map[hashValue].get(i))).key==key){
map[hashValue].remove(i);
break;
}
}
}
public boolean containsKey(int key){
int hashValue=hash(key);
for(int i=0;i<map[hashValue].size();++i){
if(((Node)(map[hashValue].get(i))).key==key){
return true;
}
}
return false;
}
private int hash(int key){
return key%base;
}
}
/**
* Your MyHashMap object will be instantiated and called as such:
* MyHashMap obj = new MyHashMap();
* obj.put(key,value);
* int param_2 = obj.get(key);
* obj.remove(key);
*/
设计哈希集合
class MyHashSet {
private int base=677;
private LinkedList[] set;
private int hash(int key){//哈希函数
return key%base; //选素数
}
public MyHashSet() {
set=new LinkedList[base];
for(int i=0;i<base;++i){
set[i]=new LinkedList<Integer>();
}
}
public void add(int key) {
if(contains(key))return;
int hashValue=hash(key);
set[hashValue].add(key);
}
public void remove(int key) {
int hashValue=hash(key);
if(contains(key)){
for(int i=0;i<set[hashValue].size();++i){
if((Integer)(set[hashValue].get(i))==key){
set[hashValue].remove(i);
break;
}
}
}
}
public boolean contains(int key) {
int hashValue=hash(key);
for(int i=0;i<set[hashValue].size();++i){
if((Integer)(set[hashValue].get(i))==key){
return true;
}
}
return false;
}
}
/**
* Your MyHashSet object will be instantiated and called as such:
* MyHashSet obj = new MyHashSet();
* obj.add(key);
* obj.remove(key);
* boolean param_3 = obj.contains(key);
*/
迭代压缩字符串
class StringIterator {
public class Node{
public char ch;
public int times;
public Node(char c,int t){
ch=c;
times=t;
}
}
List<Node>list;
int index=0;
public StringIterator(String compressedString) {
list=new ArrayList<>();
int i=0;
while(i<compressedString.length()){
char ch;
if(compressedString.charAt(i)>'9'){//英文字符
ch=compressedString.charAt(i);
++i;int num=0;
while(i<compressedString.length()&&compressedString.charAt(i)<='9'){//计算数字
num=num*10+(compressedString.charAt(i)-'0');
++i;
}
list.add(new Node(ch,num));
}
}
}
public char next() {
if(!hasNext())return ' ';
if(list.get(index).times==0){
index++;
list.get(index).times--;
return list.get(index).ch;
}
list.get(index).times--;
return list.get(index).ch;
}
public boolean hasNext() {
if(index==list.size()-1){
if(list.get(index).times==0)return false;
return true;
}return true;
}
}
/**
* Your StringIterator object will be instantiated and called as such:
* StringIterator obj = new StringIterator(compressedString);
* char param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/
最长和谐子序列
class Solution {
public int findLHS(int[] nums) {
Arrays.sort(nums);//O(NlogN)
Map<Integer,Integer>map=new HashMap<>();
for(Integer i:nums){
if(!map.containsKey(i)){
map.put(i,1);
}else{
map.put(i,map.get(i)+1);
}
}
int ans=0;
for(Integer i:nums){
if(map.containsKey(i+1)){
ans=Math.max(ans,map.get(i+1)+map.get(i));
}
}
return ans;
}
}
日志速率限制器
class Logger {
Map<String,Integer>map;
public Logger() {
map=new HashMap<>();
}
public boolean shouldPrintMessage(int timestamp, String message) {
if(!map.containsKey(message)){
map.put(message,timestamp+10);
return true;
}else{
if(map.get(message)<=timestamp){
map.put(message,timestamp+10);
return true;
}else{
return false;
}
}
//return true;
}
}
/**
* Your Logger object will be instantiated and called as such:
* Logger obj = new Logger();
* boolean param_1 = obj.shouldPrintMessage(timestamp,message);
*/
单词规律
class Solution {
public boolean wordPattern(String pattern, String s) {
String[] word=s.split(" ");
Set<String>set=new HashSet<>();
Map<Character,String>map=new HashMap<>();
if(word.length!=pattern.length())return false;
for(int i=0;i<pattern.length()&&i<word.length;++i){
if(map.containsKey(pattern.charAt(i))){
if(!map.get(pattern.charAt(i)).equals(word[i])){
return false;
}
}else{
if(set.contains(word[i])){
return false;
}else{
map.put(pattern.charAt(i),word[i]);
set.add(word[i]);
}
}
}
return true;
}
}
存在重复元素 II
class Solution {
public class Compare implements Comparator<Integer>{
public int compare(Integer o1,Integer o2){
return o1-o2;
}
}
public boolean containsNearbyDuplicate(int[] nums, int k) {
Map<Integer,List<Integer>>map=new HashMap<>();
for(int i=0;i<nums.length;++i){
if(!map.containsKey(nums[i])){
List<Integer>list=new ArrayList<>();
list.add(i);
map.put(nums[i], list);
}else{
List<Integer>list=map.get(nums[i]);
if(list.size()==1){
list.set(0,i-list.get(0));
list.add(i);
}else{
list.set(0,Math.min(list.get(0),i-list.get(1)));
list.set(1,i);
}
}
}
for(Integer key:map.keySet()){
if(map.get(key).size()>1){
if(map.get(key).get(0)<=k)return true;
}
}
return false;
}
}
同构字符串
class Solution {
public boolean isIsomorphic(String s, String t) {
Set<Character>set=new HashSet<>();
Map<Character,Character>map=new HashMap<>();
for(int i=0;i<s.length();++i){
if(map.containsKey(s.charAt(i))){//i已经映射过了
if(map.get(s.charAt(i))!=t.charAt(i))return false;
}else{
if(set.contains(t.charAt(i))){
return false;
}else{
set.add(t.charAt(i));
map.put(s.charAt(i),t.charAt(i));
}
}
}
return true;
}
}
两数之和 III - 数据结构设计
class TwoSum {
Map<Integer,Integer>map;
public TwoSum() {
map=new HashMap<>();
}
public void add(int number) {
if(!map.containsKey(number)){
map.put(number,1);
}else{
map.put(number,map.get(number)+1);
}
}
public boolean find(int value) {
for(Integer key:map.keySet()){
if(key*2==value){
if(map.get(key)>1)return true;
}else{
if(map.containsKey(value-key))return true;
}
}
return false;
}
}
/**
* Your TwoSum object will be instantiated and called as such:
* TwoSum obj = new TwoSum();
* obj.add(number);
* boolean param_2 = obj.find(value);
*/
珠玑妙算
class Solution {
public int[] masterMind(String solution, String guess) {
Map<Character,Integer>mapSolution=new HashMap<>();
Map<Character,Integer>mapGuess=new HashMap<>();
int[] ans=new int[2];
for(int i=0;i<solution.length();++i){
if(solution.charAt(i)==guess.charAt(i)){
ans[0]++;
}
else{
if(!mapSolution.containsKey(solution.charAt(i))){
mapSolution.put(solution.charAt(i),1);
}else{
mapSolution.put(solution.charAt(i),mapSolution.get(solution.charAt(i))+1);
}
if(!mapGuess.containsKey(guess.charAt(i))){
mapGuess.put(guess.charAt(i),1);
}else{
mapGuess.put(guess.charAt(i),mapGuess.get(guess.charAt(i))+1);
}
}
}
for(Character c:mapSolution.keySet()){
if(mapGuess.containsKey(c)){
ans[1]+=Math.min(mapSolution.get(c),mapGuess.get(c));
}
}
return ans;
}
}
三个有序数组的交集
class Solution {
public List<Integer> arraysIntersection(int[] arr1, int[] arr2, int[] arr3) {
List<Integer>list=new ArrayList<>();
TreeMap<Integer,Integer>map1=new TreeMap<>();
TreeMap<Integer,Integer>map2=new TreeMap<>();
TreeMap<Integer,Integer>map3=new TreeMap<>();
for(Integer i:arr1){
map1.put(i,1);
}
for(Integer i:arr2){
map2.put(i,1);
}
for(Integer i:arr3){
map3.put(i,1);
}
for(Integer key:map1.keySet()){
if(map2.containsKey(key)&&map3.containsKey(key)){
list.add(key);
}
}
return list;
}
}
两个数组的交集 II
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Map<Integer,Integer>map1=new HashMap<>();
Map<Integer,Integer>map2=new HashMap<>();
for(Integer i:nums1){
if(!map1.containsKey(i)){
map1.put(i,1);
}else{
map1.put(i,map1.get(i)+1);
}
}
for(Integer i:nums2){
if(!map2.containsKey(i)){
map2.put(i,1);
}else{
map2.put(i,map2.get(i)+1);
}
}
List<Integer>list=new ArrayList<>();
for(Integer key:map1.keySet()){
if(map2.containsKey(key)){
for(int i=0;i<Math.min(map1.get(key),map2.get(key));++i){
list.add(key);
}
}
}
int[] ans=new int[list.size()];
for(int i=0;i<ans.length;++i){
ans[i]=list.get(i);
}
return ans;
}
}
RandomPool 结构实现
设计RandomPool结构,实现如下功能:
1.insert(key) : 将某个key加入到该结构,做到不重复加入
2.delete(key) : 将原来在结构中的某个key移除
3.getRandom(): 等概率随机返回结构中的任何一个key
【要求】三个函数的时间复杂度都是O(1).
1.1 Java实现
import java.util.HashMap;
import java.util.Random;
public class RandomPoolTest {
public static class RandomPool<K>{
public int size;
public HashMap<Integer,K>keyToValue;
public HashMap<K,Integer>valueToKey;
public RandomPool() {
size=0;
keyToValue=new HashMap<>();
valueToKey=new HashMap<>();
}
//1.insert(value) : 将某个value加入到该结构,做到不重复加入
public void insert(K value) {
keyToValue.put(size, value);
valueToKey.put(value, size);
size++;
}
//2.delete(value) : 将原来在结构中的某个value移除
public void delete(K value) {
if(!valueToKey.containsKey(value))return;
int deleteKey=valueToKey.get(value);
keyToValue.put(deleteKey, keyToValue.get(size));
valueToKey.put(keyToValue.get(size), deleteKey);
keyToValue.remove(size);
size--;
}
//3.getRandom(): 等概率随机返回结构中的任何一个value
public K getRandom() {
int randomKey=new Random().nextInt(size);
return keyToValue.get(randomKey);
}
}
public static void main(String[] args) {
RandomPool<String> rp=new RandomPool<>();
rp.insert("abc");
rp.insert("cv");
rp.insert("cs");
rp.insert("12345");
rp.delete("cs");
rp.insert("hello world");
System.out.println(rp.getRandom());
System.out.println(rp.size);
}
}
1.2 C++ 实现
#include<iostream>
#include<stdio.h>
#include<vector>
#include<unordered_map>
#include<random>
#include<cstdlib>
#include<conio.h>
#include<time.h>
using namespace std;
class randomPool{
private:
unordered_map<string,int>hashMap1;
unordered_map<int,string>hashMap2;
int size;
public:
randomPool(){
size=0;
}
void insert(string str){
if(hashMap1.find(str)==hashMap1.end()){
hashMap1.insert({str,size});
hashMap2.insert({size,str});
size++;
}
}
void Delete(string str){
if(hashMap1.find(str)==hashMap1.end())return;
int deleteIndex=hashMap1[str];
string lastString=hashMap2[size];
hashMap1[lastString]=deleteIndex;
hashMap2[deleteIndex]=lastString;
}
string getRandom(){
srand(time(NULL));
int key=rand()%size;
return hashMap2[key];
}
};
int main(){
randomPool rp;
rp.insert("hello");
rp.insert("world");
rp.insert("A");
rp.insert("c");
cout<<rp.getRandom()<<endl;
rp.Delete("c");
cout<<rp.getRandom()<<endl;
return 0;
}
合并表记录
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int n=scan.nextInt();
Map<Integer,Integer>map=new HashMap<>();
int key,value;
// List<Integer>list=new ArrayList<>();
Queue<Integer>smallRootHeap=new PriorityQueue<>();
for(int i=0;i<n;++i) {
key=scan.nextInt();
value=scan.nextInt();
if(!map.containsKey(key)) {
map.put(key,value);
smallRootHeap.add(key);
}
else {
map.put(key, map.get(key)+value);
}
}
while(!smallRootHeap.isEmpty()) {
System.out.println(smallRootHeap.peek()+" "+map.get(smallRootHeap.peek()));
smallRootHeap.poll();
}
}
}
两数之和等于目标值
import java.util.*;
public class Solution {
/**
*
* @param numbers int整型一维数组
* @param target int整型
* @return int整型一维数组
*/
public int[] twoSum (int[] numbers, int target) {
// write code here
Map<Integer,Integer>map=new HashMap<>();
for(int i=0;i<numbers.length;++i){
map.put(numbers[i],i+1);
}
int[] ans=new int[2];
for(int i=0;i<numbers.length;++i){
if(map.containsKey(target-numbers[i])&&map.get(target-numbers[i])!=i+1){
ans[0]=i+1;
ans[1]=map.get(target-numbers[i]);
break;
}
}
return ans;
}
}
不重复数字
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
//不重复数字
public class Main {
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int N=scan.nextInt();
for(int i=0;i<N;++i) {
int n=scan.nextInt();
scan.nextLine();
List<String>list=new ArrayList<>();
Set<String>set=new HashSet<>();
String x;
x=scan.nextLine();
String[] numbers=x.split(" ");
for(String s:numbers)
if(!set.contains(s)) {
list.add(s);
set.add(s);
}
for(String a:list) {
System.out.print(a+" ");
}
System.out.println();
}
}
}
问题分析:
测试数据比较大,如果一个一个输入,会运行超时,需要一整行一整行接收输入(Java很烦人的地方) 。