From f3e88db25c67e6d1dabd862734a02a3b71a93f45 Mon Sep 17 00:00:00 2001 From: markilue <745518019@qq.com> Date: Tue, 27 Dec 2022 12:48:31 +0800 Subject: [PATCH] =?UTF-8?q?leecode=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{IsAnagram.java => T01_IsAnagram.java} | 2 +- ...ntersection.java => T02_Intersection.java} | 2 +- .../leecode/hashtable/T03_IsHappy.java | 113 ++++++++++++++ .../{TwoSum.java => T04_TwoSum.java} | 2 +- ...ourSumCount.java => T05_FourSumCount.java} | 2 +- .../hashtable/second/T01_IsAnagram.java | 66 ++++++++ .../hashtable/second/T02_Intersection.java | 90 +++++++++++ .../leecode/hashtable/second/T04_TwoSum.java | 68 +++++++++ .../hashtable/second/T05_FourSumCount.java | 142 ++++++++++++++++++ 9 files changed, 483 insertions(+), 4 deletions(-) rename Leecode/src/main/java/com/markilue/leecode/hashtable/{IsAnagram.java => T01_IsAnagram.java} (99%) rename Leecode/src/main/java/com/markilue/leecode/hashtable/{Intersection.java => T02_Intersection.java} (98%) create mode 100644 Leecode/src/main/java/com/markilue/leecode/hashtable/T03_IsHappy.java rename Leecode/src/main/java/com/markilue/leecode/hashtable/{TwoSum.java => T04_TwoSum.java} (99%) rename Leecode/src/main/java/com/markilue/leecode/hashtable/{FourSumCount.java => T05_FourSumCount.java} (99%) create mode 100644 Leecode/src/main/java/com/markilue/leecode/hashtable/second/T01_IsAnagram.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/hashtable/second/T02_Intersection.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/hashtable/second/T04_TwoSum.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/hashtable/second/T05_FourSumCount.java diff --git a/Leecode/src/main/java/com/markilue/leecode/hashtable/IsAnagram.java b/Leecode/src/main/java/com/markilue/leecode/hashtable/T01_IsAnagram.java similarity index 99% rename from Leecode/src/main/java/com/markilue/leecode/hashtable/IsAnagram.java rename to Leecode/src/main/java/com/markilue/leecode/hashtable/T01_IsAnagram.java index 78aaff6..784fcd5 100644 --- a/Leecode/src/main/java/com/markilue/leecode/hashtable/IsAnagram.java +++ b/Leecode/src/main/java/com/markilue/leecode/hashtable/T01_IsAnagram.java @@ -14,7 +14,7 @@ import java.util.HashMap; * 注意:若s 和 t中每个字符出现的次数都相同,则称s 和 t互为字母异位词。 * @Version: 1.0 */ -public class IsAnagram { +public class T01_IsAnagram { @Test diff --git a/Leecode/src/main/java/com/markilue/leecode/hashtable/Intersection.java b/Leecode/src/main/java/com/markilue/leecode/hashtable/T02_Intersection.java similarity index 98% rename from Leecode/src/main/java/com/markilue/leecode/hashtable/Intersection.java rename to Leecode/src/main/java/com/markilue/leecode/hashtable/T02_Intersection.java index f924cd6..5c3265b 100644 --- a/Leecode/src/main/java/com/markilue/leecode/hashtable/Intersection.java +++ b/Leecode/src/main/java/com/markilue/leecode/hashtable/T02_Intersection.java @@ -17,7 +17,7 @@ import java.util.Set; * 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 * @Version: 1.0 */ -public class Intersection { +public class T02_Intersection { @Test public void test(){ diff --git a/Leecode/src/main/java/com/markilue/leecode/hashtable/T03_IsHappy.java b/Leecode/src/main/java/com/markilue/leecode/hashtable/T03_IsHappy.java new file mode 100644 index 0000000..9e7d60f --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hashtable/T03_IsHappy.java @@ -0,0 +1,113 @@ +package com.markilue.leecode.hashtable; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.Set; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hashtable + *@Author: dingjiawen + *@CreateTime: 2022-12-27 11:06 + *@Description: + * TODO 力扣202题 快乐数: + * 编写一个算法来判断一个数 n 是不是快乐数。 + * 「快乐数」 定义为: + * 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 + * 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。 + * 如果这个过程 结果为 1,那么这个数就是快乐数。 + * 如果 n 是 快乐数 就返回 true ;不是,则返回 false 。 + *@Version: 1.0 + */ +public class T03_IsHappy { + + @Test + public void test(){ + int n=19; + System.out.println(isHappy(n)); + } + + @Test + public void test1(){ + int n=2; + System.out.println(isHappy(n)); + } + + /** + * 思路:利用hashset记录重复的,一旦重复了就进入了循环,那么直接返回false + * 速度击败81.35%,内存击败42.29% 1ms + * @param n + * @return + */ + public boolean isHappy(int n) { + + HashSet set = new HashSet<>(); + set.add(n); + while (n!=1){ + int next=0; + //计算各个位置之和 + while (n!=0){ + int num = n % 10; + next+=num*num; + n/=10; + } + if(set.contains(next)){ + //已经开始循环,直接开始返回 + return false; + }else { + set.add(next); + n=next; + } + } + return true; + + } + + /** + * 官方hash思路:与本人hash + * 利用hashset记录重复的,一旦重复了就进入了循环或者等于1,那么就可以返回了 + * 速度击败81.35%,内存击败67.9% 1ms + * 时间复杂度O(logn) + * @param n + * @return + */ + public boolean isHappy1(int n) { + + Set seen = new HashSet<>(); + while (n != 1 && !seen.contains(n)) { + seen.add(n); + n = getNext(n); + } + return n == 1; + } + + private int getNext(int n) { + int totalSum = 0; + while (n > 0) { + int d = n % 10; + n = n / 10; + totalSum += d * d; + } + return totalSum; + } + + + /** + * 官方快慢指针法:核心还是监测是否有环;如果有环,那么快的一定可以和慢的相遇 + * 速度击败100% + * @param n + * @return + */ + public boolean isHappy2(int n) { + int slowRunner = n; + int fastRunner = getNext(n); + while (fastRunner != 1 && slowRunner != fastRunner) { + slowRunner = getNext(slowRunner); + fastRunner = getNext(getNext(fastRunner)); + } + return fastRunner == 1; + } + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hashtable/TwoSum.java b/Leecode/src/main/java/com/markilue/leecode/hashtable/T04_TwoSum.java similarity index 99% rename from Leecode/src/main/java/com/markilue/leecode/hashtable/TwoSum.java rename to Leecode/src/main/java/com/markilue/leecode/hashtable/T04_TwoSum.java index b547e31..10b5fcc 100644 --- a/Leecode/src/main/java/com/markilue/leecode/hashtable/TwoSum.java +++ b/Leecode/src/main/java/com/markilue/leecode/hashtable/T04_TwoSum.java @@ -19,7 +19,7 @@ import java.util.HashMap; * @Version: 1.0 */ -public class TwoSum { +public class T04_TwoSum { @Test public void test(){ diff --git a/Leecode/src/main/java/com/markilue/leecode/hashtable/FourSumCount.java b/Leecode/src/main/java/com/markilue/leecode/hashtable/T05_FourSumCount.java similarity index 99% rename from Leecode/src/main/java/com/markilue/leecode/hashtable/FourSumCount.java rename to Leecode/src/main/java/com/markilue/leecode/hashtable/T05_FourSumCount.java index 398c834..4c0d2fc 100644 --- a/Leecode/src/main/java/com/markilue/leecode/hashtable/FourSumCount.java +++ b/Leecode/src/main/java/com/markilue/leecode/hashtable/T05_FourSumCount.java @@ -19,7 +19,7 @@ import java.util.HashSet; * 2) nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0 * @Version: 1.0 */ -public class FourSumCount { +public class T05_FourSumCount { @Test diff --git a/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T01_IsAnagram.java b/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T01_IsAnagram.java new file mode 100644 index 0000000..a62c93d --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T01_IsAnagram.java @@ -0,0 +1,66 @@ +package com.markilue.leecode.hashtable.second; + +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hashtable.second + *@Author: dingjiawen + *@CreateTime: 2022-12-27 10:01 + *@Description: + * TODO 二刷242题 有效的字母异位词: + * 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 + * 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。 + *@Version: 1.0 + */ +public class T01_IsAnagram { + + @Test + public void test(){ + String s = "anagram"; + String t = "nagaram"; + + System.out.println(isAnagram(s,t)); + } + + @Test + public void test1(){ + String s = "rat"; + String t = "car"; + + System.out.println(isAnagram(s,t)); + } + + /** + * 思路:统计个字符出现的次数,再作比较即可 + * 由于字符都是小写字母,所以可以用数组存 + * @param s + * @param t + * @return + */ + public boolean isAnagram(String s, String t) { + int[] sArray = new int[26]; +// int[] tArray = new int[26]; + + char[] chars1 = s.toCharArray(); + char[] chars2 = t.toCharArray(); + + for (int i = 0; i < chars1.length; i++) { + sArray[chars1[i]-'a']++; + } + + for (int i = 0; i < chars2.length; i++) { + sArray[chars2[i]-'a']--; + } + + for (int i = 0; i < sArray.length; i++) { + if(sArray[i]!=0){ + return false; + } + } + + return true; + + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T02_Intersection.java b/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T02_Intersection.java new file mode 100644 index 0000000..4a0e106 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T02_Intersection.java @@ -0,0 +1,90 @@ +package com.markilue.leecode.hashtable.second; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hashtable.second + *@Author: dingjiawen + *@CreateTime: 2022-12-27 10:45 + *@Description: + * TODO 二刷349题 两个数组的交集: + * 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 + *@Version: 1.0 + */ +public class T02_Intersection { + + @Test + public void test(){ + int[] nums1 = {1, 2, 2, 1}; + int[] nums2 = {2, 2}; + System.out.println(Arrays.toString(intersection(nums1,nums2))); + } + + @Test + public void test1(){ + int[] nums1 = {4,9,5}; + int[] nums2 = {9,4,9,8,4}; + System.out.println(Arrays.toString(intersection(nums1,nums2))); + } + + /** + * 思路:唯一且不要求顺序:hashset + * 速度击败98.76%,内存击败13.48% 1ms + * @param nums1 + * @param nums2 + * @return + */ + public int[] intersection(int[] nums1, int[] nums2) { + HashSet set = new HashSet<>(); + for (int i : nums1) { + set.add(i); + } + int size=0; +// int length=Math.max(nums1.length,nums2.length); + int[] result = new int[set.size()]; + + for (int i : nums2) { + if(set.contains(i)){ + result[size++]=i; + set.remove(i); + } + } + return Arrays.copyOf(result,size); + + + } + + /** + * 官方最快:使用一个boolean[]来代替hashSet + * 速度击败100%,内存击败52.55% 0ms + * @param nums1 + * @param nums2 + * @return + */ + public int[] intersection1(int[] nums1, int[] nums2) { + boolean[] flag = new boolean[1001]; + ArrayList integers = new ArrayList<>(); + for(int i :nums1){ + flag[i] = true; + } + for(int j :nums2){ + if(flag[j]){ + integers.add(j); + flag[j] = false; + } + } + int[] ints = new int[integers.size()]; + for(int i = 0;i + * 速度击败78.74%,内存击败14.5% + * @param nums + * @param target + * @return + */ + public int[] twoSum(int[] nums, int target) { + + HashMap map = new HashMap<>(); + + for (int i = 0; i < nums.length; i++) { + Integer find = map.getOrDefault( nums[i], -1); + if(find!=-1){ + //找到了 + return new int[]{find,i}; + }else { + map.put(target-nums[i],i); + } + } + return new int[2]; + } + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T05_FourSumCount.java b/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T05_FourSumCount.java new file mode 100644 index 0000000..4c92b80 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hashtable/second/T05_FourSumCount.java @@ -0,0 +1,142 @@ +package com.markilue.leecode.hashtable.second; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hashtable.second + *@Author: dingjiawen + *@CreateTime: 2022-12-27 12:10 + *@Description: + * TODO 二刷454题 四数相加 II: + * 给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: + * 0 <= i, j, k, l < n + * nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0 + *@Version: 1.0 + */ +public class T05_FourSumCount { + + @Test + public void test(){ + int[] nums1 = {1, 2}, nums2 = {-2, -1}, nums3 = {-1, 2}, nums4 = {0, 2}; + System.out.println(fourSumCount(nums1,nums2,nums3,nums4)); + } + + @Test + public void test1(){ + int[] nums1 = {0}, nums2 = {0}, nums3 = {0}, nums4 = {0}; + System.out.println(fourSumCount(nums1,nums2,nums3,nums4)); + } + + /** + * 思路:这题求得是组合数,而不要求里面到底是那四个index, + * 考虑两个nums两两组成map + * 速度击败62.9%,内存击败24.56% 143% + * @param nums1 + * @param nums2 + * @param nums3 + * @param nums4 + * @return + */ + public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) { + + HashMap map = new HashMap<>(); + for (int i : nums1) { + for (int i1 : nums2) { + map.put(i+i1,map.getOrDefault(i+i1,0)+1); + } + } + HashMap map1 = new HashMap<>(); + for (int i : nums3) { + for (int i1 : nums4) { + map1.put(i+i1,map1.getOrDefault(i+i1,0)+1); + } + } + int result=0; + for (Integer integer : map.keySet()) { + result+=map1.getOrDefault(-integer,0)*map.get(integer); + } + return result; + + } + + /** + * 官方hash解法:比本人少用一次hashmap,直接在for循环里面加即可 + * 速度击败82.48%,内存击败5.1% + * @param A + * @param B + * @param C + * @param D + * @return + */ + public int fourSumCount1(int[] A, int[] B, int[] C, int[] D) { + Map countAB = new HashMap(); + for (int u : A) { + for (int v : B) { + countAB.put(u + v, countAB.getOrDefault(u + v, 0) + 1); + } + } + int ans = 0; + for (int u : C) { + for (int v : D) { + if (countAB.containsKey(-u - v)) { + ans += countAB.get(-u - v); + } + } + } + return ans; + } + + /** + * 官方题解中最快的解法: + * 速度击败99.95%,内存击败10.31% 47ms + * @param nums1 + * @param nums2 + * @param nums3 + * @param nums4 + * @return + */ + public int fourSumCount2(int[] nums1, int[] nums2, int[] nums3, int[] nums4) { + Arrays.sort(nums1); + Arrays.sort(nums2); + Arrays.sort(nums3); + Arrays.sort(nums4); + + int resultCounter = 0; + Map numMap = new HashMap<>(); + + for (int i = 0; i < nums1.length; i++) { + int iStart = i; + //重复就加快循环 + while (i + 1 < nums1.length && nums1[i] == nums1[i + 1]) { + i++; + } + for (int j = 0; j < nums2.length; j++) { + int jStart = j; + while (j + 1 < nums2.length && nums2[j] == nums2[j + 1]) { + j++; + } + numMap.put(nums1[i] + nums2[j], numMap.getOrDefault(nums1[i] + nums2[j], 0) + (i-iStart+1) * (j-jStart+1)); + } + } + for (int i = 0; i < nums3.length; i++) { + int iStart = i; + while (i + 1 < nums3.length && nums3[i] == nums3[i + 1]) { + i++; + } + for (int j = 0; j < nums4.length; j++) { + int jStart = j; + while (j + 1 < nums4.length && nums4[j] == nums4[j + 1]) { + j++; + } + resultCounter += numMap.getOrDefault(-nums3[i]-nums4[j], 0) * (i - iStart + 1) * (j - jStart + 1); + } + } + return resultCounter; + } + +}