有效的字母异位词 LeetCode 242
题目链接:LeetCode 242 - 简单
思路
第一想法是使用HashMap,但是后期发现使用数组更加方便。
HashMap:
java
class Solution {
public boolean isAnagram(String s, String t) {
if(s.length()!=t.length()){
return false;
}
HashMap<Character,Integer> map = new HashMap<>();
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
map.put(c,map.getOrDefault(c, 0) + 1);
}
for(int i=0;i<t.length();i++){
char c = t.charAt(i);
map.put(c,map.getOrDefault(c, 0) - 1);
if(map.get(c)<0){
return false;
}
}
return true;
}
}
总结
- map.getOrDefault(c, 0)如果HashMap中存在c元素的话,获取该value,否则设置为0。
- 使用数组进行所占的内存更少:
class Solution {
public boolean isAnagram(String s, String t) {
int[] c = new int[26];
for(int i=0;i<s.length();i++){
c[s.charAt(i)-'a']++;
}
for(int i=0;i<t.length();i++){
c[t.charAt(i)-'a']--;
}
for(int recond:c){
if(recond!=0){
return false;
}
}
return true;
}
}
代码的优化问题-> 将
for(int i=0;i<26;i++){
if(c[i]!=0){
return false;
}
}
优化为
for(int recond:c){
if(recond!=0){
return false;
}
}
两个数组的交集 LeetCode 349
题目链接:LeetCode 349 - 简单
思路
第一想法是使用HashMap,但是在写代码的时候,发现HashMap使用的过程中,发现使用Set的方式会更好,因为题目中对于相同的数字效果一样。
HashSet:
java
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if(nums1 == null || nums1.length==0 || nums2 == null || nums2.length ==0){
return new int[0];
}
HashSet<Integer> set = new HashSet<>();
HashSet<Integer> resultSet = new HashSet<>();
for(int num:nums1){
set.add(num);
}
for(int num:nums2){
if(set.contains(num)){
resultSet.add(num);
}
}
return resultSet.stream().mapToInt(x -> x).toArray();
}
}
总结
- 使用HashMap的方法:
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
if(nums1 == null || nums1.length ==0 || nums2 == null || nums2.length ==0){
return new int[0];
}
HashMap<Integer,Integer> map = new HashMap<>();
HashMap<Integer,Integer> resultMap = new HashMap<>();
for(int num:nums1){
map.put(num,map.getOrDefault(num,0)+1);
}
for(int num:nums2){
if(map.containsKey(num)){
resultMap.put(num,resultMap.getOrDefault(num,0)+1);
}
}
return resultMap.keySet().stream().mapToInt(x -> x).toArray();
}
}
与Set的差异为 1)set.contains(num)替换为map.containsKey(num) 2)将resultSet替换为resultMap.keySet()
- return resultSet.stream().mapToInt(x -> x).toArray();也可以替换为如下代码:
int[] arr = new int[resSet.size()];
int j = 0;
for(int i : resSet){
arr[j++] = i;
}
return arr;
快乐数 LeetCode 202
题目链接:LeetCode 202 - 简单
思路
看到题意理解,需要解决的是两点,①如何处理循环 ②如何处理每个数
HashSet:
java
class Solution {
public boolean isHappy(int n) {
HashSet<Integer> set = new HashSet<>();
while( n!=1 && !set.contains(n)){
set.add(n);
n = getNextNumber(n);
}
return n == 1;
}
private int getNextNumber(int n){
int res = 0;
while( n > 0 ){
int num = n % 10;
res += num * num;
n /= 10;
}
return res;
}
}
总结
- 使用HashSet来解决循环问题,如果数字之前出现过,那么这个数就不是快乐数,并且退出循环
- 如何解决每个数,使用%和/
两数之和 LeetCode 1
哈希
题目链接:LeetCode 1 - 简单
思路
第一个想法就是两个for循环去查找
时间复杂度0(n^2):
java
class Solution {
public int[] twoSum(int[] nums, int target) {
int i=0,j=0;
for(i=0;i<nums.length-1;i++){
int targetNum = target - nums[i];
for(j=i+1;j<nums.length;j++){
if(nums[j]==targetNum){
int[] result = {i,j};
return result;
}
}
}
int[] result = {i,j};
return result;
}
}
总结
该题目可以使用HashMap来解决: ①使用HashMap可以使得两数相加在O(n)的时间复杂度内完成 ②使用HashMap而不是使用HashSet的原因是:可以使用key 和 value的组合,存储之前数组中数的下标。
class Solution {
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
if(nums == null || nums.length==0){
return res;
}
Map<Integer, Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
int targetNum = target - nums[i];
if(map.containsKey(targetNum)){
res[0] = map.get(targetNum);
res[1] = i;
return res;
}
map.put(nums[i],i);
}
return res;
}
}
3.15次二刷:
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> map = new HashMap<>();
int index1 = 0;
int index2 = 0;
for(int i=0;i<nums.length;i++){
map.put(nums[i],i);
}
for(int i=0;i<nums.length;i++){
int num = target - nums[i];
if(map.containsKey(num)){
index1 = i;
if(map.get(num)!=index1){
index2 = map.get(num);
break;
}
}
}
return new int[]{index1,index2};
}
}
但是代码不够精炼,修改一下:
class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
int num = target - nums[i];
if(map.containsKey(num)){
int j = map.get(num);
return new int[]{j,i};
}else{
map.put(nums[i],i);
}
}
return null;
}
}
该两数之和算法采用的是哈希的做法。主要是通过在hashmap中查找是否存在num,如果找到,则返回结果,如果没有找到,则将当前的下标和值放入到hashmap中,继续下一次循环。
49. 字母异位词分组
哈希 hot100
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 = new String(c);
List<String> list = map.getOrDefault(key, new ArrayList<String>());
list.add(s);
map.put(key, list);
}
return new ArrayList<List<String>>(map.values());
}
}
主要就是将单词sort后,异位的单词都一样,因此放到同一个hash的key中。
-> hash解决的问题 1、已知一个target,和另一个num1,求num2是否存在的问题 2、相同的字符串组成的String