目录
哈希表
主要利用hashmap的键值对特点,进行数据的处理。
个人总结的一段常用代码:
map中某个键对应的值需要改变+1的时候,先取出该键对应的值,再把该值加1之后重新放入map中。
if(map.containsKey(key1)){
int tempcount = map.get(keys)+1;
map.put(key1,tempcount);
}
题目一:变位词组
(题目链接:https://leetcode-cn.com/problems/group-anagrams-lcci)
编写一种方法,对字符串数组进行排序,将所有变位词组合在一起。变位词是指字母相同,但排列不同的字符串。
注意:本题相对原题稍作修改
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
方法:使用hashmap存储结构进行数据的存储,其中key存的字符串包含字母相同并且也顺序相同的,value存储的包含字母相同但是也顺序不同的
Java源代码
import java.util.*;
public class hashword {
public static void main(String[] args) {
String[] strs = new String[]{"eat", "tea", "tan", "ate", "nat", "bat"};
List<List<String>> strs2 = new ArrayList<List<String>>();
Map<String, List<String>> map = new HashMap<String, List<String>>();
for (int i = 0; i <strs.length ; i++) {
char[] arr = strs[i].toCharArray();
Arrays.sort(arr);
String arrstr = new String(arr);
if(!map.containsKey(arrstr)){
List<String> templiststring = new ArrayList<>();
templiststring.add(strs[i]);
map.put(arrstr,templiststring);
}
else{
map.get(arrstr).add(strs[i]);
}
}
for(String key :map.keySet()){
strs2.add(map.get(key));
}
System.out.println("value: "+strs2);
}
}
最重要的步骤:
记得对要处理的字符串转换为字符数组,然后对字符数组进行排序。
【注意】:思路总结:新的哈希结构HashMap<String, List<String>>();注意,这是我之前没有的思维,即map中key和value传统是一一对应的,
但是我们把value的数据结构形式定位list<String>,这样实质上实现了一对多的存储,此种哈希思维注意总结
【注意】:语法总结:把字符数组变为字符串,我们使用String arrstr = new String(arr);
把字符串变成字符数组,我们使用char[] arr = str.toCharArray();
【注意】:语法总结:Arrays.sort(arr)可以实现数组的自动排序
题目二:两数之和
(题目链接:https://leetcode-cn.com/problems/two-sum)
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6
输出:[0,1]
方法一:直接for循环,比较简单,我们不在展示代码
方法二:此处主要讲解使用哈希的方法解题
官方思路:使用hash表来存储数组的值和数组的索引:数组的值对应与hashtable的key,数组的索引对应hashtable的value。
通过一个for循环,判断target-nums[i]是否在hashtable中,如果在,则找到了,返回结果即可,如果不在,则把num[i],和i存储到hashtable中。
Java源代码
import java.util.HashMap;
import java.util.Map;
public class twocount_sum {
public static void main(String[] args) {
int[] nums = new int[]{2,6,7,15};
int target = 9;
int result[] = new int[2];
Map<Integer,Integer> hashtable = new HashMap<Integer,Integer>();
for (int i = 0; i < nums.length; i++) {
if(hashtable.containsKey(target - nums[i])){
result[0] = i ;
result[1] = hashtable.get(target-nums[i]);
}else{
hashtable.put(nums[i], i);
}
}
for (int i = 0; i < 2; i++) {
System.out.println(result[i]);
}
}
}
第二次写的代码:
import java.util.*;
public class Solution {
/**
*
* @param numbers int整型一维数组
* @param target int整型
* @return int整型一维数组
*/
public int[] twoSum (int[] numbers, int target) {
// write code here
int[] res = new int[2];
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for(int i =0;i<numbers.length;i++){
map.put(numbers[i],i+1);
}
for(int i =0;i<numbers.length;i++){
if(map.containsKey(target - numbers[i])){
if( (i+1) != map.get(target - numbers[i])){
res[0] = i+1;
res[1] = map.get(target-numbers[i]);
break;
}
}
}
return res;
}
}
题目三:数对和
(题目链接:https://leetcode-cn.com/problems/pairs-with-sum-lcci/)
设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。
示例 1:
输入: nums = [5,6,5], target = 11
输出: [[5,6]]
示例 2:
输入: nums = [5,6,5,6], target = 11
输出: [[5,6],[5,6]]
思路:利用hashtable进行数组中元素存储
官方:后续研究一下官方的简洁代码
Java源代码:
class Solution {
public List<List<Integer>> pairSums(int[] nums, int target) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
Map<Integer,Integer> map1 = new HashMap<Integer, Integer>();
for (int i = 0; i < nums.length; i++) {
if(map1.containsKey(nums[i])){
int tempcount = map1.get(nums[i]) +1;
map1.put(nums[i] , tempcount);
}else{
map1.put(nums[i],1);
}
}
for (int i = 0; i < nums.length; i++) {
if(map1.containsKey(target- nums[i]) ){
if(map1.get(target - nums[i]) >0){
//System.out.println("first: "+nums[i]+" second: "+(int)(target- nums[i]));
int tempcount2 = map1.get(target - nums[i])-1;
map1.put( target - nums[i],tempcount2);
if(map1.get(nums[i]) >0){
List<Integer> tempres = new ArrayList<Integer>();
tempres.add(nums[i]);
tempres.add((int)(target- nums[i]));
res.add(tempres);
}
int tempcount3 = map1.get(nums[i])-1;
map1.put(nums[i],tempcount3);
}
}
}
return res;
}
}
题目四:有效的字母异位词
(题目链接:https://leetcode-cn.com/problems/valid-anagram/)
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例 1:
输入: s = "anagram", t = "nagaram"
输出: true
示例 2:
输入: s = "rat", t = "car"
输出: false
方法一:把字符串变成字符数组,对字符数组排序,排序后的字符数组变成字符串,判断两个字符串是否相等。
Java源代码:
class Solution {
public boolean isAnagram(String s, String t) {
char[] chars = s.toCharArray();
Arrays.sort(chars);
char[] chart = t.toCharArray();
Arrays.sort(chart);
if(Arrays.toString(chars).equals(Arrays.toString(chart))){
return true;
}else {
return false;
}
}
}
方法二:采用一个数组,判断每个字符出现的次数。
官方方法:遍历第一个字符串,出现某个字符,则出现次数加1,遍历第二个字符串,出现某个字符,则统计好的次数减1
class Solution {
public boolean isAnagram(String s, String t) {
int[] table = new int[26];
for (int i = 0; i < s.length(); i++) {
table[s.charAt(i)-'a']++;
}
for (int i = 0; i < t.length(); i++) {
table[t.charAt(i)-'a']--;
}
for (int i = 0; i < 26; i++) {
if(table[i]!=0){
return false;
}
}
return true;
}
}
第二次写的代码
class Solution {
public boolean isAnagram(String s, String t) {
Map<Character,Integer> map = new HashMap<Character,Integer>();
int slength = s.length();
int tlength = t.length();
if(slength != tlength){
return false;
}else{
for(int i =0;i<slength;i++){
if(map.containsKey(s.charAt(i))){
int tempcount = map.get(s.charAt(i))+1;
map.put(s.charAt(i),tempcount);
}else{
map.put(s.charAt(i),1);
}
}
for(int j =0;j<tlength;j++){
if(map.containsKey(t.charAt(j))){
int tempcount2 = map.get(t.charAt(j))-1;
map.put(t.charAt(j),tempcount2);
}else{
return false;
}
}
for(char key:map.keySet()){
if(map.get(key)!=0){
return false;
}
}
return true;
}
}
}
题目五:有多少个数字相当于当前数字
(题目链接:https://leetcode-cn.com/problems/how-many-numbers-are-smaller-than-the-current-number/)
给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。
换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 nums[j] < nums[i] 。
以数组形式返回答案。
示例 1:
输入:nums = [8,1,2,2,3]
输出:[4,0,1,1,3]
解释:
对于 nums[0]=8 存在四个比它小的数字:(1,2,2 和 3)。
对于 nums[1]=1 不存在比它小的数字。
对于 nums[2]=2 存在一个比它小的数字:(1)。
对于 nums[3]=2 存在一个比它小的数字:(1)。
对于 nums[4]=3 存在三个比它小的数字:(1,2 和 2)。
思路:直接两重for循环,暴力法解决
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int[] res = new int[nums.length];
for(int i =0;i<res.length;i++){
res[i]=0;
}
for(int i =0; i< nums.length;i++){
for(int j =0; j<nums.length;j++){
if(nums[i]>nums[j]){
res[i]++;
}
}
}
return res;
}
}
题目六:森林中的兔子
链接:https://leetcode-cn.com/problems/rabbits-in-forest
森林中,每个兔子都有颜色。其中一些兔子(可能是全部)告诉你还有多少其他的兔子和自己有相同的颜色。我们将这些回答放在 answers 数组里。
返回森林中兔子的最少数量。
示例:
输入: answers = [1, 1, 2]
输出: 5
解释:
两只回答了 "1" 的兔子可能有相同的颜色,设为红色。
之后回答了 "2" 的兔子不会是红色,否则他们的回答会相互矛盾。
设回答了 "2" 的兔子为蓝色。
此外,森林中还应有另外 2 只蓝色兔子的回答没有包含在数组中。
因此森林中兔子的最少数量是 5: 3 只回答的和 2 只没有回答的。
输入: answers = [10, 10, 10]
输出: 11
输入: answers = []
输出: 0
思路:主要找到逻辑的关键:
假设回答 k 的兔子的数量为 v = count[k],通过上面分析可以知道至少有 a 只兔子,其中 a 是满足 a >= count[k] 的最小 k + 1 的倍数。
class Solution {
public int numRabbits(int[] answers) {
int res = 0;
Map<Integer,Integer> hashtable = new HashMap<Integer,Integer>();
for (int i = 0; i <answers.length ; i++) {
if(hashtable.containsKey(answers[i])){
int temp = hashtable.get(answers[i])+1;
hashtable.put(answers[i],temp);
}else{
hashtable.put(answers[i],1);
}
}
for (int key : hashtable.keySet()){
for(int i =1; ;i++){
int curr = (key+1)*i;
if(curr >= hashtable.get(key)){
res = res + curr;
break;
}
}
}
return res;
}
}
题目七:根据字符出现频率排序
(链接:https://leetcode-cn.com/problems/sort-characters-by-frequency/)
给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
示例 1:
输入:
"tree"
输出:
"eert"
解释:
'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
思路:采用hash表存储各个字符及它们出现的频率,根据hash表的value进行大小排序,进行输出
class Solution {
public String frequencySort(String s) {
Map<Character,Integer> hashtable = new HashMap<Character,Integer>();
for (int i = 0; i < s.length(); i++) {
char curr = s.charAt(i);
if(hashtable.containsKey(curr)){
int currcount=hashtable.get(curr)+1;
hashtable.put(curr,currcount);
}else{
hashtable.put(curr,1);
}
}
int[] value = new int[hashtable.size()];
int i = 0;
char[] key = new char[hashtable.size()];
int j =0;
for(Character keyi: hashtable.keySet()){
value[i++] = hashtable.get(keyi);
key[j++] = keyi;
}
//System.out.println(Arrays.toString(key));
//System.out.println(Arrays.toString(value));
for (int k = 0; k < value.length-1; k++) {
for (int l = 0; l < value.length-k-1; l++) {
if(value[l] < value[l+1]){
int temp = value[l];
value[l] = value[l+1];
value[l+1] = temp;
char temp2 = key[l];
key[l] = key[l+1];
key[l+1] = temp2;
}
}
}
String res="";
for (int k = 0; k < key.length; k++) {
for (int l = 0; l < value[k]; l++) {
res += key[k];
}
}
return res;
}
}