leecode更新

This commit is contained in:
markilue 2023-02-27 14:36:26 +08:00
parent 6d39eb279d
commit 667ca9a0b9
4 changed files with 386 additions and 0 deletions

View File

@ -0,0 +1,96 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-02-27 10:47
*@Description:
* TODO 力扣第1题:
* 给定一个整数数组 nums 和一个整数目标值 target请你在该数组中找出 和为目标值 target 的那 两个 整数并返回它们的数组下标
* 你可以假设每种输入只会对应一个答案但是数组中同一个元素在答案里不能重复出现
* 你可以按任意顺序返回答案
*@Version: 1.0
*/
public class T01_TwoSum {
@Test
public void test(){
int[] nums = {2, 7, 11, 15};
int target = 9;
System.out.println(twoSum(nums,target));
}
/**
* map记录
* 速度击败77.1% 内存击败30.65% 2ms
* @param nums
* @param target
* @return
*/
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();//<need,index>
int need = 0;
Integer index;
for (int i = 0; i < nums.length; i++) {
need = target - nums[i];
index = map.getOrDefault(need, -1);
if (index != -1) {
return new int[]{index, i};//找到了
} else {
map.put(nums[i], i);
}
}
return new int[2];
}
/**
* 官方最快
* 类似于双指针
* 速度击败100% 内存击败30.65% 0ms
* @param nums
* @param target
* @return
*/
public int[] twoSum1(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
int[] arr = new int[2];
int left = 0;
int right = nums.length-1;
while(left<=right){
if(map.containsKey(nums[left])){
arr[0] = map.get(nums[left]);
arr[1] = left;
return arr;
} else {
map.put(target-nums[left],left);
}
if(map.containsKey(nums[right])){
arr[0] = map.get(nums[right]);
arr[1] = right;
return arr;
} else {
map.put(target-nums[right],right);
}
left++;
right--;
}
return arr;
}
}

View File

@ -0,0 +1,100 @@
package com.markilue.leecode.hot100;
import com.markilue.leecode.listnode.ListNode;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-02-27 11:15
*@Description:
* TODO 力扣2题 两数相加:
* 给你两个 非空 的链表表示两个非负的整数它们每位数字都是按照 逆序 的方式存储的并且每个节点只能存储 一位 数字
* 请你将两个数相加并以相同形式返回一个表示和的链表
* 你可以假设除了数字 0 之外这两个数都不会以 0 开头
*@Version: 1.0
*/
public class T02_AddTwoNumbers {
/**
* 思路:递归法 每个节点只能存储一个数字,多的数字需要进位
* 速度击败100% 内存击败45.35% 1ms
* @param l1
* @param l2
* @return
*/
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return addTwoNumbers(l1, l2, false);
}
/**
*
* @param l1
* @param l2
* @param flag 是否需要进位
* @return
*/
public ListNode addTwoNumbers(ListNode l1, ListNode l2, boolean flag) {
//为了公共统一如果某一个为null,可以给他初始化
if (l1 == null && l2 == null) {
if (flag) return new ListNode(1);
return null;
} else if (l1 == null) {
l1 = new ListNode(0);
} else if (l2 == null) {
l2 = new ListNode(0);
}
ListNode fakeHead = new ListNode(0);
int var = l1.val + l2.val;
if (flag) {
var += 1;
}
fakeHead.val = var % 10;
fakeHead.next = addTwoNumbers(l1.next, l2.next, var >= 10);
return fakeHead;
}
/**
* 官方解法: 使用head,tail指针进行记录 值得借鉴
* 速度击败100% 内存击败94.81% 1ms
* @param l1
* @param l2
* @return
*/
public ListNode addTwoNumbers1(ListNode l1, ListNode l2) {
ListNode head = null, tail = null;
int carry = 0;
while (l1 != null || l2 != null) {
int n1 = l1 != null ? l1.val : 0;
int n2 = l2 != null ? l2.val : 0;
int sum = n1 + n2 + carry;
if (head == null) {
head = tail = new ListNode(sum % 10);
} else {
tail.next = new ListNode(sum % 10);
tail = tail.next;
}
carry = sum / 10;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (carry > 0) {
tail.next = new ListNode(carry);
}
return head;
}
}

View File

@ -0,0 +1,109 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-02-27 12:46
*@Description:
* TODO 力扣3题 无重复字符的最长子串:
* 给定一个字符串 s 请你找出其中不含有重复字符的 最长子串 的长度
*@Version: 1.0
*/
public class T03_LengthOfLongestSubstring {
@Test
public void test() {
String s = "dvdf";
String s1 = "abba";
System.out.println(lengthOfLongestSubstring(s1));
}
/**
* 思路:注意是子串不是子序列
* 使用一个hashmap记录之前是否有过这个单词
* 速度击败87.4% 内存击败75.84% 4ms
* @param s
* @return
*/
public int lengthOfLongestSubstring(String s) {
char[] chars = s.toCharArray();
Map<Character, Integer> map = new HashMap<>();//<key,index>
int maxLength = 0;
int lastIndex = 0;
int length = 0;
for (int i = 0; i < chars.length; i++) {
if (map.containsKey(chars[i])) {
lastIndex = Math.max(lastIndex, map.get(chars[i]) + 1);//上次存在索引就挪到这个词的下一个
}
length = i - lastIndex + 1;//长度
if (length > maxLength) maxLength = length;
map.put(chars[i], i);//如果存在就会覆盖
}
return maxLength;
}
/**
* 官方最快:使用数组来代替map
* 速度击败1005 内存击败68.17% 1ms
* @param s
* @return
*/
public int lengthOfLongestSubstring1(String s) {
int[] last = new int[128];
for(int i = 0; i < 128; i++) {
last[i] = -1;
}
int n = s.length();
int res = 0;
int start = 0;
for(int i = 0; i < n; i++) {
int index = s.charAt(i);
start = Math.max(start, last[index] + 1);
res = Math.max(res, i - start + 1);
last[index] = i;
}
return res;
}
/**
* 评论区动态规划法
* 速度击败100% 内存击败91.56% 1ms
* @param s
* @return
*/
public int lengthOfLongestSubstring2(String s) {
int m = s.length();
if(m==0) {
return 0;
}
int num =1; //初始值表示以s的第一个字符为结束的不重复的最长子串
int max =1;
for(int i=1;i<m;i++){
int index = s.indexOf(s.charAt(i),i-num);
if(index<i) { //num更新表示以s的第i+1个字符为结束的不重复的最长子串
num = i-index;
} else {
num = num+1;
}
max = Math.max(max,num);
}
return max;
}
}

View File

@ -0,0 +1,81 @@
package com.markilue.leecode.hot100;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-02-27 13:25
*@Description:
* TODO 力扣4题 寻找两个正序数组的中位数
* 给定两个大小分别为 m n 的正序从小到大数组 nums1 nums2请你找出并返回这两个正序数组的 中位数
* 算法的时间复杂度应该为 O(log (m+n))
*@Version: 1.0
*/
public class T04_FindMedianSortedArrays {
/**
* 思路:先逐个找找到时间复杂度为O(m+n)
* 速度击败100% 内存击败25.42% 1ms
* @param nums1
* @param nums2
* @return
*/
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
int len = m + n;
int left = -1, right = -1;
int aStart = 0, bStart = 0;
for (int i = 0; i <= len / 2; i++) {//必须遍历到threshold的位置才出去
left = right;
if (aStart < m && (bStart >= n || nums1[aStart] < nums2[bStart])) {//判断条件是关键
right = nums1[aStart++];
} else {
right = nums2[bStart++];
}
}
if ((len & 1) == 0)
return (left + right) / 2.0;
else
return right;
}
/**
* 时间复杂度O(log(m+n)) 每次比较k/2的位置 抛弃一半
* 速度击败100% 内存击败45.86% 1ms
* @param nums1
* @param nums2
* @return
*/
public double findMedianSortedArrays1(int[] nums1, int[] nums2) {
int n = nums1.length;
int m = nums2.length;
int left = (n + m + 1) / 2;
int right = (n + m + 2) / 2;
//将偶数和奇数的情况合并如果是奇数会求两次同样的 k
return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;
}
private int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) {
int len1 = end1 - start1 + 1;
int len2 = end2 - start2 + 1;
// len1 的长度小于 len2这样就能保证如果有数组空了一定是 len1
if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
if (len1 == 0) return nums2[start2 + k - 1];
if (k == 1) return Math.min(nums1[start1], nums2[start2]);
//会直接比较k/2的位置
int i = start1 + Math.min(len1, k / 2) - 1;
int j = start2 + Math.min(len2, k / 2) - 1;
if (nums1[i] > nums2[j]) {
return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
}
else {
return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
}
}
}