leecode更新

This commit is contained in:
markilue 2023-03-03 14:53:40 +08:00
parent 36913ce39e
commit b1eeb7c60c
7 changed files with 648 additions and 0 deletions

View File

@ -0,0 +1,64 @@
package com.markilue.leecode.hot100;
import com.markilue.leecode.listnode.ListNode;
import com.markilue.leecode.listnode.ListNodeUtils;
import org.junit.Test;
import java.lang.reflect.Array;
import java.util.Arrays;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-03 10:11
*@Description:
* TODO 力扣19题 删除链表的倒数第N个节点:
* 给你一个链表删除链表的倒数第 n 个结点并且返回链表的头结点
*@Version: 1.0
*/
public class T13_RemoveNthFromEnd {
@Test
public void test(){
ListNode root = ListNodeUtils.build(new int[]{1, 2, 3, 4, 5});
ListNode listNode = removeNthFromEnd(root, 6);
ListNodeUtils.print(listNode);
}
/**
* 快慢指针:一个先走N步,然后两个指针一起走
* @param head
* @param n
* @return
*/
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode fakeHead = new ListNode();
fakeHead.next = head;
ListNode fast = fakeHead;
ListNode slow = fakeHead;
//快指针先走n步
while (fast != null && n != 0) {
fast = fast.next;
n--;
}
//n不够
if (fast == null) {
return fakeHead.next;
}
//快指针走到头
while (fast.next != null) {
fast = fast.next;
slow = slow.next;
}
//删除slow
slow.next = slow.next.next;
return fakeHead.next;
}
}

View File

@ -0,0 +1,130 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.*;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-03 10:29
*@Description:
* TODO 力扣20题 有效的括号:
* 给定一个只包括 '('')''{''}''['']' 的字符串 s 判断字符串是否有效
* 有效字符串需满足
* 左括号必须用相同类型的右括号闭合
* 左括号必须以正确的顺序闭合
* 每个右括号都有一个对应的相同类型的左括号
*@Version: 1.0
*/
public class T14_IsValid {
@Test
public void test() {
String s = "()";
System.out.println(isValid(s));
}
/**
* 思路:核心就是对称消除 使用stack消栈
* 速度击败48.96% 内存击败43.9% 2ms
* @param s
* @return
*/
public boolean isValid(String s) {
char[] chars = s.toCharArray();
Stack<Character> stack = new Stack<>();
Map<Character, Character> map = new HashMap() {{
put(')', '(');
put(']', '[');
put('}', '{');
}};
for (char aChar : chars) {
if (!map.containsKey(aChar)) {
stack.push(aChar);
} else {
if (stack.isEmpty() || map.get(aChar) != stack.pop()) {//这里记得将判空
return false;
}
}
}
if (!stack.isEmpty()) {//这里也要记得加判空
return false;
}
return true;
}
public boolean isValid1(String s) {
char[] chars = s.toCharArray();
Deque<Character> stack = new LinkedList<>();
Map<Character, Character> map = new HashMap() {{
put(')', '(');
put(']', '[');
put('}', '{');
}};
for (char aChar : chars) {
if (!map.containsKey(aChar)) {
stack.push(aChar);
} else {
if (stack.isEmpty() || map.get(aChar) != stack.pop()) {//这里记得将判空
return false;
}
}
}
if (!stack.isEmpty()) {//这里也要记得加判空
return false;
}
return true;
}
/**
* 官方优秀的解答:使用数组代替stack
* 速度击败100% 内存击败29.16% 0ms
* @param s
* @return
*/
public boolean isValid2(String s) {
if(s == null || s.length()==0){
return true;
}
char[] str = s.toCharArray();
int N = str.length;
int size = 0;
char[] stack=new char[N];
for (int i=0;i<N;i++){
char cha = str[i];
if(cha=='('||cha=='['|| cha=='{'){
stack[size++] = cha =='('?')':(cha=='['?']':'}');
}else {
if(size == 0){
return false;
}
char last = stack[--size];
if(cha != last ){
return false;
}
}
}
return size == 0;
}
}

View File

@ -0,0 +1,81 @@
package com.markilue.leecode.hot100;
import com.markilue.leecode.listnode.ListNode;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-03 10:50
*@Description:
* TODO 力扣21题 合并两个有序链表:
* 将两个升序链表合并为一个新的 升序 链表并返回新链表是通过拼接给定的两个链表的所有节点组成的
*@Version: 1.0
*/
public class T15_MergeTwoLists {
/**
* 思路:递归谁小合并谁
* 速度击败100% 内存击败83% 0ms
* @param list1
* @param list2
* @return
*/
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
}
if (list2 == null) {
return list1;
}
ListNode root = new ListNode();
if (list1.val < list2.val) {
root.val = list1.val;
root.next = mergeTwoLists(list1.next, list2);
} else {
root.val = list2.val;
root.next = mergeTwoLists(list1, list2.next);
}
return root;
}
public ListNode mergeKLists(ListNode[] lists) {
if(lists == null || lists.length == 0){
return null;
}
return merge(lists,0,lists.length - 1);
}
public ListNode merge(ListNode[] lists , int left , int right){
if(left == right) {return lists[left];}
int middle = left + (right - left)/2;
ListNode list1 = merge(lists,left,middle);
ListNode list2 = merge(lists,middle + 1,right);
return mergeTwoList(list1,list2);
}
public ListNode mergeTwoList(ListNode head1, ListNode head2){
ListNode dummy = new ListNode();
ListNode cur = dummy; // cur指向当前合并链表的最后一个
while(head1!=null && head2!=null){
if(head1.val <= head2.val){
cur.next = head1;
head1 = head1.next;
}else{
cur.next = head2;
head2 = head2.next;
}
cur = cur.next;
}
cur.next = head1==null?head2:head1;
return dummy.next;
}
}

View File

@ -0,0 +1,105 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-03 10:56
*@Description:
* TODO 力扣22题 括号生成:
* 数字 n 代表生成括号的对数请你设计一个函数用于能够生成所有可能的并且 有效的 括号组合
*@Version: 1.0
*/
public class T16_GenerateParenthesis {
@Test
public void test() {
System.out.println(generateParenthesis(1));
}
List<String> result = new ArrayList<>();
StringBuilder cur = new StringBuilder();
/**
* 思路:有效的括号 实际上就是前面的(要比)要多那就是有效的括号
* 速度击败75.47% 内存击败39.67% 1ms
* @param n
* @return
*/
public List<String> generateParenthesis(int n) {
backtracking(n, 0, 0);
return result;
}
/**
*
* @param n 需要生成多少对括号
* @param x 当前有多少个(
* @param y 当前有多少个)
*/
public void backtracking(int n, int x, int y) {
if (x < y || x > n || y > n) {
//非有效括号
return;
}
if (n == x && n == y) {
//遍历完了并且符合要求
result.add(new String(cur));
return;
}
for (int i = 0; i < 2; i++) {
if (i == 0) {
cur.append('(');
backtracking(n, x + 1, y);
} else {
cur.append(')');
backtracking(n, x, y + 1);
}
cur.deleteCharAt(cur.length() - 1);//回溯
}
}
/**
* 官方最快:本质上与本人一致只是把判断简化了
* 速度击败100% 内存击败66.13% 0ms
* @param n
* @return
*/
public List<String> generateParenthesis1(int n) {
List<String> result = new ArrayList<>();
StringBuilder sb = new StringBuilder();
backTrack(result, sb, 0, 0, n);
return result;
}
private void backTrack(List<String> result, StringBuilder sb, int left, int right, int n) {
if (sb.length() == n * 2) {
result.add(sb.toString());
return;
}
if (left < n) {
sb.append('(');
backTrack(result, sb, left + 1, right, n);
sb.deleteCharAt(sb.length() - 1);
}
if (right < left) {
sb.append(')');
backTrack(result, sb, left, right + 1, n);
sb.deleteCharAt(sb.length() - 1);
}
}
}

View File

@ -0,0 +1,118 @@
package com.markilue.leecode.hot100;
import com.markilue.leecode.listnode.ListNode;
import com.markilue.leecode.listnode.ListNodeUtils;
import org.junit.Test;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-03 11:18
*@Description:
* TODO 力扣23题 合并k个升序链表:
* 给你一个链表数组每个链表都已经按升序排列
* 请你将所有链表合并到一个升序链表中返回合并后的链表
*@Version: 1.0
*/
public class T17_MergeKLists {
@Test
public void test() {
ListNode[] listNodes = new ListNode[3];
listNodes[0] = ListNodeUtils.build(new int[]{1, 4, 5});
listNodes[1] = ListNodeUtils.build(new int[]{1,3,4});
listNodes[2] = ListNodeUtils.build(new int[]{2, 6});
ListNodeUtils.print(mergeKLists(listNodes));
}
/**
* 思路:二分法再合并
* 速度击败74.86% 内存击败96.99% 3ms
* @param lists
* @return
*/
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) {
return null;
}
return split(lists, 0, lists.length - 1);
}
public ListNode split(ListNode[] lists, int start, int end) {
if (start == end) {
return lists[start];
}
int mid = start + ((end - start) >> 1);
ListNode left = split(lists, start, mid);
ListNode right = split(lists, mid + 1, end);
return merge(left, right);
}
public ListNode merge(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
}
if (list2 == null) {
return list1;
}
ListNode root = new ListNode();
if (list1.val < list2.val) {
root.val = list1.val;
root.next = merge(list1.next, list2);
} else {
root.val = list2.val;
root.next = merge(list1, list2.next);
}
return root;
}
/**
* 官方最快:同样是分治法
* 速度击败80.97% 内存击败32.68% 2ms
* @param lists
* @return
*/
public ListNode mergeKLists1(ListNode[] lists) {
if(lists == null || lists.length == 0){
return null;
}
return merge(lists,0,lists.length - 1);
}
public ListNode merge(ListNode[] lists , int left , int right){
if(left == right) {return lists[left];}
int middle = left + (right - left)/2;
ListNode list1 = merge(lists,left,middle);
ListNode list2 = merge(lists,middle + 1,right);
return mergeTwoList(list1,list2);
}
public ListNode mergeTwoList(ListNode head1, ListNode head2){
ListNode dummy = new ListNode();
ListNode cur = dummy; // cur指向当前合并链表的最后一个
while(head1!=null && head2!=null){
if(head1.val <= head2.val){
cur.next = head1;
head1 = head1.next;
}else{
cur.next = head2;
head2 = head2.next;
}
cur = cur.next;
}
cur.next = head1==null?head2:head1;
return dummy.next;
}
}

View File

@ -0,0 +1,150 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.Arrays;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-03 11:40
*@Description:
* TODO 力扣31题 下一个排列:
* 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列
* 例如arr = [1,2,3] 以下这些都可以视作 arr 的排列[1,2,3][1,3,2][3,1,2][2,3,1]
* 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列
* 更正式地如果数组的所有排列根据其字典顺序从小到大排列在一个容器中
* 那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列
* 如果不存在下一个更大的排列那么这个数组必须重排为字典序最小的排列其元素按升序排列
* 例如arr = [1,2,3] 的下一个排列是 [1,3,2]
* 类似地arr = [2,3,1] 的下一个排列是 [3,1,2]
* arr = [3,2,1] 的下一个排列是 [1,2,3] 因为 [3,2,1] 不存在一个字典序更大的排列
* 给你一个整数数组 nums 找出 nums 的下一个排列
* 必须 原地 修改只允许使用额外常数空间
*@Version: 1.0
*/
public class T18_NextPermutation {
@Test
public void test1(){
// int[] nums ={1,2,3};
int[] nums ={3,2,1};
nextPermutation(nums);
System.out.println(Arrays.toString(nums));
}
/**
* 思路:从后往前遍历寻找第一个当前数比前一个数大的进行交换 如果找不到就进行整体的排序
* 有问题: 没有想象的那么简单
* 还有一个思路是: 先有小到大排序 通过回溯(树层去重后)找到原来的数那么回溯的下一个值就是需要的值
* 这有一个问题就是 使用了额外的空间 第二是时间复杂度应该为O(2^N)
* @param nums
*/
public void nextPermutation(int[] nums) {
int i = nums.length - 1;
for (; i > 0; i--) {
if (nums[i] > nums[i - 1]) {
exchange(nums, i, i - 1);
break;
}
}
if (i == 0) {
quickSort(nums);
}
}
@Test
public void test(){
int[] nums={5,6,4,8,2,9,1,7,3};
quickSort(nums);
System.out.println(Arrays.toString(nums));
}
public void quickSort(int[] nums) {
partition(nums,0,nums.length-1);
}
public void partition(int[] nums, int i, int j) {
if (i >= j) {
return;
}
int mid = sort(nums, i, j);
partition(nums, i, mid - 1);//排左边
partition(nums, mid + 1, j);//排右边
}
public int sort(int[] nums, int i, int j) {
int left = i;
int right = j+1;
int num = nums[i];
while (left < right) {
while (left < j && nums[++left] < num) {
continue;
}
while (0 < right && nums[--right] > num) {
continue;
}
if (left >= right) {
break;
}
exchange(nums, left, right);
}
exchange(nums, right, i);
return right;
}
public void exchange(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
/**
* 官方解答的思路:两边扫描具体看笔记
* 速度击败100% 内存击败58.73% 0ms
* @param nums
*/
public void nextPermutation1(int[] nums) {
int i = nums.length - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) {
i--;
}
if (i >= 0) {
int j = nums.length - 1;
while (j >= 0 && nums[i] >= nums[j]) {
j--;
}
swap(nums, i, j);
}
reverse(nums, i + 1);
}
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public void reverse(int[] nums, int start) {
int left = start, right = nums.length - 1;
while (left < right) {
swap(nums, left, right);
left++;
right--;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B