leecode更新
This commit is contained in:
parent
6d39eb279d
commit
667ca9a0b9
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue