leecode更新

This commit is contained in:
markilue 2023-03-07 14:36:05 +08:00
parent b5dc4022bc
commit 6eafee1860
5 changed files with 384 additions and 0 deletions

View File

@ -0,0 +1,128 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import javax.swing.event.ListDataEvent;
import java.util.*;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-07 10:17
*@Description:
* TODO 力扣49题 字母异位词分组:
* 给你一个字符串数组请你将 字母异位词 组合在一起可以按任意顺序返回结果列表
* 字母异位词 是由重新排列源单词的字母得到的一个新单词所有源单词中的字母通常恰好只用一次
*@Version: 1.0
*/
public class T26_GroupAnagrams {
@Test
public void test() {
String[] str={"eat", "tea", "tan", "ate", "nat", "bat"};
// String[] str = {""};
// String[] str = {"ac","c"};
System.out.println(groupAnagrams(str));
}
List<List<String>> result = new ArrayList<>();
List<String> cur = new ArrayList<>();
Map<Character, Integer> map = new HashMap<>();
Map<Integer,Map<Character, Integer>> bigMap=new HashMap<>();
//TODO 超出时间限制第111个无法通过;修改后使用bigmap只在空的时候记录通过 :速度击败5% 内存击败5%
public List<List<String>> groupAnagrams(String[] strs) {
boolean[] used = new boolean[strs.length];//记录这个单词是否被使用过
for (int i = 0; i < strs.length; i++) {
if (!used[i]) {
used[i] = true;
addMap(strs[i],map,i);
cur.add(strs[i]);
for (int j = i + 1; j < strs.length; j++) {
if (!used[j] && isAnagrams(strs[j],j)) {
cur.add(strs[j]);
used[j] = true;
}
}
result.add(new ArrayList<>(cur));
cur.clear();
map.clear();
}
}
return result;
}
public void addMap(String str,Map<Character,Integer> map,int index) {
for (int i = 0; i < str.length(); i++) {
char key = str.charAt(i);
map.put(key, map.getOrDefault(key, 0) + 1);
}
bigMap.put(index, map);
}
public boolean isAnagrams(String curStr,int index) {
Map<Character, Integer> curMap = bigMap.getOrDefault(index, new HashMap<>());
if(curMap.isEmpty()){
addMap(curStr,curMap,index);
}
return curMap.equals(map);
}
/**
* 官方计数法:由于互为字母异位词的两个字符串包含的字母相同
* 因此两个字符串中的相同字母出现的次数一定是相同的
* 故可以将每个字母出现的次数使用字符串表示作为哈希表的键
* 速度击败26.63% 内存击败22.41% 10ms
* @param strs
* @return
*/
public List<List<String>> groupAnagrams1(String[] strs) {
Map<String, List<String>> map = new HashMap<String, List<String>>();
for (String str : strs) {
int[] counts = new int[26];
int length = str.length();
for (int i = 0; i < length; i++) {
counts[str.charAt(i) - 'a']++;
}
// 将每个出现次数大于 0 的字母和出现次数按顺序拼接成字符串作为哈希表的键
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 26; i++) {
if (counts[i] != 0) {
sb.append((char) ('a' + i));
sb.append(counts[i]);
}
}
String key = sb.toString();
List<String> list = map.getOrDefault(key, new ArrayList<String>());
list.add(str);
map.put(key, list);
}
return new ArrayList<List<String>>(map.values());
}
/**
* 官方合理且最快:通过排序建立key
* 速度击败80.36% 内存击败57.98% 6ms
* @param strs
* @return
*/
public List<List<String>> groupAnagrams2(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
char[] cs = str.toCharArray();
Arrays.sort(cs);
String key = String.valueOf(cs);
List<String> list = map.getOrDefault(key, new ArrayList<>());
list.add(str);
map.put(key, list);
}
return new ArrayList(map.values());
}
}

View File

@ -0,0 +1,85 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-07 11:38
*@Description:
* TODO 力扣53题 最大子数组和:
* 给你一个整数数组 nums 请你找出一个具有最大和的连续子数组子数组最少包含一个元素返回其最大和
* 子数组 是数组中的一个连续部分
*@Version: 1.0
*/
public class T27_MaxSubArray {
@Test
public void test(){
int[] nums={-2,-1};
System.out.println(maxSubArray1(nums));
}
/**
* 贪心:要尽可能多的数字如果等于0了直接抛弃
* 速度击败100% 内存击败79.27%
* @param nums
* @return
*/
public int maxSubArray(int[] nums) {
int cur = 0;
int maxValue = Integer.MIN_VALUE;
for (int i = 0; i < nums.length; i++) {
cur += nums[i];
if (maxValue < cur) maxValue = cur;
if (cur < 0) cur = 0;
}
return maxValue;
}
/**
* 动态规划: dp定义为使用nums[0-i]的最大子数组和
* 速度击败2.9% 内存击败5.9% 15ms
* @param nums
* @return
*/
public int maxSubArray1(int[] nums) {
// if(nums.length==0)return nums[0];
int[][] dp = new int[nums.length][2];
dp[0][0] = Integer.MIN_VALUE;//至少要一个
dp[0][1] = nums[0];//至少要一个
for (int i = 1; i < nums.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], dp[i-1][1]);//现在就不要全不要
dp[i][1] = Math.max(dp[i - 1][1] + nums[i], nums[i]);//要之前还是不要之前
}
return Math.max(dp[dp.length-1][0],dp[dp.length-1][1]);
}
/**
* 动态规划: 滚动数组优化
* 速度击败100% 内存击败68.67% 1ms
* @param nums
* @return
*/
public int maxSubArray2(int[] nums) {
// if(nums.length==0)return nums[0];
int dp0 = Integer.MIN_VALUE;//至少要一个
int dp1 = nums[0];//至少要一个
for (int i = 1; i < nums.length; i++) {
dp0 = Math.max(dp0, dp1);//现在就不要全不要
dp1 = Math.max(dp1 + nums[i], nums[i]);//要之前还是不要之前
}
return Math.max(dp0,dp1);
}
}

View File

@ -0,0 +1,41 @@
package com.markilue.leecode.hot100;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-07 13:14
*@Description:
* TODO 力扣55题 跳跃游戏:
* 给定一个非负整数数组 nums 你最初位于数组的 第一个下标
* 数组中的每个元素代表你在该位置可以跳跃的最大长度
* 判断你是否能够到达最后一个下标
*@Version: 1.0
*/
public class T28_CanJump {
/**
* 思路:贪心记录一个能到的最大索引
* 速度击败94.51% 内存击败97.5% 2ms
* @param nums
* @return
*/
public boolean canJump(int[] nums) {
if(nums.length==1)return true;
int maxIndex = 0;
int curIndex = 0;
for (int i = 0; i < nums.length - 1 && i <= maxIndex; i++) {
curIndex = i + nums[i];
if (curIndex > maxIndex) maxIndex = curIndex;
if (maxIndex >= nums.length - 1) return true;
}
return false;
}
}

View File

@ -0,0 +1,84 @@
package com.markilue.leecode.hot100;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-07 13:24
*@Description:
* TODO 力扣56题 合并区间:
* 以数组 intervals 表示若干个区间的集合其中单个区间为 intervals[i] = [starti, endi]
* 请你合并所有重叠的区间并返回 一个不重叠的区间数组该数组需恰好覆盖输入中的所有区间
*@Version: 1.0
*/
public class T29_Merge {
/**
* 根据start排序如果end<start则有重叠区间 7ms
* @param intervals
* @return
*/
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
List<int[]> list = new ArrayList<>();
for (int[] interval : intervals) {
if (list.isEmpty() || list.get(list.size() - 1)[1] < interval[0]) {
list.add(interval);
} else {
int length = list.size() - 1;
int[] last = list.get(length);
last[1] = Math.max(last[1], interval[1]);
}
}
return list.toArray(new int[0][0]);
}
/**
* 官方较快解法:6ms
* @param intervals
* @return
*/
public int[][] merge1(int[][] intervals) {
//按xstart排序
Arrays.sort(intervals, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
//优化 但是需要警惕超过int范围
return o1[0] - o2[0];
}
});
//寻找重叠区间并进行合并
int length=0;//记录新数组的长度
int[][] result =new int[intervals.length][2];
result[0]=intervals[0];
int lastEnd=intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
if(lastEnd>=intervals[i][0]){
//重叠区间需要合并
lastEnd=Math.max(lastEnd,intervals[i][1]);
result[length][1]=lastEnd;
}else {
//非重叠区间直接添加
length++;
result[length]=intervals[i];
lastEnd=intervals[i][1];
}
}
//缩短至result的真实长度
return Arrays.copyOf(result,length+1);
}
}

View File

@ -0,0 +1,46 @@
package com.markilue.leecode.hot100;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-07 13:40
*@Description:
* TODO 力扣62题 不同路径:
* 一个机器人位于一个 m x n 网格的左上角 起始点在下图中标记为 Start
* 机器人每次只能向下或者向右移动一步机器人试图达到网格的右下角在下图中标记为 Finish
* 问总共有多少条不同的路径
*@Version: 1.0
*/
public class T30_UniquePaths {
/**
* 思路:动态规划法 ->当前的位置可以是上面往下走一步也可以是左边往右边走一步
* 速度击败100% 内存击败16.37% 0ms
* @param m
* @param n
* @return
*/
public int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
for (int i = 0; i < m; i++) {
dp[i][0] = 1;
}
for (int i = 0; i < n; i++) {
dp[0][i] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
}