leecode更新

This commit is contained in:
markilue 2023-04-26 10:14:34 +08:00
parent 03bc9f9c6b
commit e9ab1f5244
8 changed files with 634 additions and 3 deletions

View File

@ -0,0 +1,51 @@
package com.markilue.leecode.hot100.second;
import com.markilue.leecode.listnode.ListNode;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100.second
*@Author: markilue
*@CreateTime: 2023-04-25 10:12
*@Description:
* TODO 力扣23 合并K个升序链表:
* 给你一个链表数组每个链表都已经按升序排列
* 请你将所有链表合并到一个升序链表中返回合并后的链表
*@Version: 1.0
*/
public class T17_23_MergeKLists {
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) return null;
return merge(lists, 0, lists.length - 1);
}
public ListNode merge(ListNode[] lists, int start, int end) {
if (start >= end) return lists[start];
int mid = start + ((end - start) >> 1);
ListNode list1 = merge(lists, start, mid);
ListNode list2 = merge(lists, mid + 1, end);
return mergeTwoList(list1, list2);
}
private ListNode mergeTwoList(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
} else if (list2 == null) {
return list1;
}
ListNode root = new ListNode(0);
if (list1.val < list2.val) {
root.val = list1.val;
root.next = mergeTwoList(list1.next, list2);
} else {
root.val = list2.val;
root.next = mergeTwoList(list1, list2.next);
}
return root;
}
}

View File

@ -0,0 +1,62 @@
package com.markilue.leecode.hot100.second;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100.second
*@Author: markilue
*@CreateTime: 2023-04-25 10:25
*@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_31_NextPermutation {
/**
* 下一个排列:从后往前找第一个不是递增的然后交换然后将后面的全部反转
* @param nums
*/
public void nextPermutation(int[] nums) {
int index = nums.length - 2;
while (index >= 0 && nums[index] >= nums[index + 1]) {
index--;
}
if (index >= 0) {
//交换第一个比他大的数
int j = nums.length - 1;
while (j >= 0 && nums[index] >= nums[j]) {//注意这些地方都是要等于
j--;
}
swap(nums, index, j);
}
reverse(nums, index + 1, nums.length-1);
}
public void swap(int[] nums, int left, int right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
swap(nums, start, end);
start++;
end--;
}
}
}

View File

@ -2,6 +2,8 @@ package com.markilue.leecode.hot100.second;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
/**
@ -17,7 +19,7 @@ import java.util.LinkedList;
public class T19_32_LongestValidParentheses {
@Test
public void test(){
public void test() {
String s = ")()())";
System.out.println(longestValidParentheses(s));
}
@ -43,8 +45,8 @@ public class T19_32_LongestValidParentheses {
stack.pop();
if (stack.isEmpty()) {
stack.push(i);
}else {
length = Math.max(i-stack.peek() , length);
} else {
length = Math.max(i - stack.peek(), length);
}
}
@ -53,4 +55,31 @@ public class T19_32_LongestValidParentheses {
return length;
}
public int longestValidParentheses1(String s) {
Deque<Integer> stack = new ArrayDeque<>();//入栈的时候对应的index
stack.push(-1);
int result = 0;
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '(') {
stack.push(i);
} else {
stack.pop();
if (stack.isEmpty()) {
stack.push(i);
}else {
result = Math.max(result, i - stack.peek());
}
}
}
return result;
}
}

View File

@ -0,0 +1,111 @@
package com.markilue.leecode.hot100.second;
import org.junit.Test;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100.second
*@Author: markilue
*@CreateTime: 2023-04-25 10:49
*@Description:
* TODO 力扣33 搜索旋转排序数组:
* 整数数组 nums 按升序排列数组中的值 互不相同
* 在传递给函数之前nums 在预先未知的某个下标 k0 <= k < nums.length上进行了 旋转使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]下标 0 开始 计数例如 [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2]
* 给你 旋转后 的数组 nums 和一个整数 target 如果 nums 中存在这个目标值 target 则返回它的下标否则返回 -1
* 你必须设计一个时间复杂度为 O(log n) 的算法解决此问题
*@Version: 1.0
*/
public class T20_33_Search {
@Test
public void test() {
int[] nums = {1, 3};
System.out.println(search(nums, 3));
}
//递归法
public int search(int[] nums, int target) {
return searchTwo(nums, 0, nums.length - 1, target);
}
public int searchTwo(int[] nums, int start, int end, int target) {
if (start >= end) {
if (nums[start] == target) {
return start;
} else {
return -1;
}
}
int mid = start + ((end - start) >> 1);
if (nums[mid] >= nums[0]) {
if (nums[mid] < target) {
return searchTwo(nums, mid + 1, end, target);
} else if (nums[mid] > target) {
if (target >= nums[0]) {
return searchTwo(nums, start, mid - 1, target);
} else {
return searchTwo(nums, mid + 1, end, target);
}
} else {
return mid;
}
} else {
if (nums[mid] < target) {
if (nums[0] > target) {
return searchTwo(nums, mid + 1, end, target);
} else {
return searchTwo(nums, start, mid - 1, target);
}
} else if (nums[mid] > target) {
return searchTwo(nums, start, mid - 1, target);
} else {
return mid;
}
}
}
//优雅while的search
public int search1(int[] nums, int target) {
int n = nums.length;
if (n == 0) {
return -1;
}
if (n == 1) {
return nums[0] == target ? 0 : -1;
}
int left = 0;
int right = n - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] == target) {
return mid;
}
if (nums[0] <= nums[mid]) {//TODO 主要这里要等于就是将不翻转的情况也包含进行
if (nums[0] <= target && nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
} else {
if (nums[mid] < target && target <= nums[n - 1]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
}

View File

@ -0,0 +1,51 @@
package com.markilue.leecode.hot100.second;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100.second
*@Author: markilue
*@CreateTime: 2023-04-25 11:24
*@Description:
* TODO 力扣34 在排序数组中查找元素的第一个和最后一个位置:
* 给你一个按照非递减顺序排列的整数数组 nums和一个目标值 target请你找出给定目标值在数组中的开始位置和结束位置
* 如果数组中不存在目标值 target返回 [-1, -1]
* 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题
*@Version: 1.0
*/
public class T21_34_SearchRange {
public int[] searchRange(int[] nums, int target) {
int n = nums.length;
if (n == 0) {
return new int[]{-1, -1};
}
if (n == 1) {
return nums[0] == target ? new int[]{0, 0} : new int[]{-1, -1};
}
int left = 0;
int right = n - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
int left1 = mid;
int right1 = mid;
while (left1 > 0 && nums[left1-1] == nums[mid]) {
left1--;
}
while (right1 < nums.length-1 && nums[right1+1] == nums[mid]) {
right1++;
}
return new int[]{left1, right1};
}
}
return new int[]{-1, -1};
}
}

View File

@ -0,0 +1,65 @@
package com.markilue.leecode.hot100.second;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100.second
*@Author: markilue
*@CreateTime: 2023-04-25 11:55
*@Description:
* TODO 力扣39 组和总和:
* 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target 找出 candidates 中可以使数字和为目标数 target 所有 不同组合 并以列表形式返回你可以按 任意顺序 返回这些组合
* candidates 中的 同一个 数字可以 无限制重复被选取 如果至少一个数字的被选数量不同则两种组合是不同的
* 对于给定的输入保证和为 target 的不同组合数少于 150
*@Version: 1.0
*/
public class T22_39_CombinationSum {
@Test
public void test() {
int[] nums = {2, 3, 6, 7};
System.out.println(combinationSum(nums, 7));
}
List<Integer> cur = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
/**
*
* @param candidates
* @param target
* @return
*/
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backtracking(candidates, target, 0);
return result;
}
public void backtracking(int[] candidates, int target, int startIndex) {
if (target == 0) {
result.add(new ArrayList<>(cur));
return;
}
if (startIndex >= candidates.length) return;
for (int i = 0; target - candidates[startIndex] * i >= 0; i++) {
for (int j = 0; j < i; j++) {
cur.add(candidates[startIndex]);
}
backtracking(candidates, target - i * candidates[startIndex], startIndex + 1);
for (int j = 0; j < i; j++) {
cur.remove(cur.size()-1);
}
}
}
}

View File

@ -0,0 +1,192 @@
package com.markilue.leecode.interview.meituan;
import org.junit.Test;
import java.util.*;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.interview.meituan
*@Author: markilue
*@CreateTime: 2023-04-22 14:55
*@Description: TODO
*@Version: 1.0
*/
public class test1 {
public int maxScore(int[] price, int k) {
int n = price.length;
Arrays.sort(price); // 将宝石按价格从小到大排序
// 计算最小分数
int minScore = 0;
for (int i = 0; i < k; i++) {
minScore += price[i];
}
// 计算最大分数
int maxScore = minScore + price[n - 1] * k; // 最大分数的范围在[minScore, maxScore]之间
while (minScore < maxScore) {
int midScore = minScore + (maxScore - minScore) / 2;
if (check(price, k, midScore)) { // 如果当前最大分数可行则继续往上调整
minScore = midScore + 1;
} else { // 否则往下调整
maxScore = midScore;
}
}
return maxScore - minScore;
}
// 判断当前最大分数是否可行
private boolean check(int[] price, int k, int maxScore) {
int n = price.length;
int[] bag = new int[n]; // bag[i]表示第i个宝石所在的行囊编号初始值为-1表示没有被放入行囊中
int[] capacity = new int[k]; // capacity[i]表示第i个行囊还能容纳多少宝石初始值为k
Arrays.fill(bag, -1); // 初始化bag数组
Arrays.fill(capacity, k); // 初始化capacity数组
int i = n - 1; // 从价格最高的宝石开始往下放
while (i >= 0) {
int j = findNext(bag, price[i]); // 找到下一个可以放入宝石的行囊编号
if (j == -1) { // 如果没有可用的行囊则当前最大分数不可行
return false;
}
int l = findLeft(bag, j, price[i]); // 找到行囊j中宝石的最左边位置
int r = findRight(bag, j, price[i]); // 找到行囊j中宝石的最右边位置
if (r - l + 1 <= capacity[j]) { // 如果行囊j可以容纳当前宝石
for (int p = l; p <= r; p++) { // [l,r]之间的宝石全部放入行囊j中
bag[p] = j;
}
capacity[j] -= r - l + 1; // 更新行囊j的容量
i--; // 处理下一个宝石
} else { // 如果行囊j不能容纳当前宝石则需要找下一个行囊
i++; // 回溯到上一个宝石
j = findPrev(bag, j); // 找到上一个可用的行囊编号
if (j == -1) { // 如果没有可用的行囊则当前最大分数不可行
return false;
}
l = findLeft(bag, j, price[i]); // 找到行囊j中宝石的最左边位置
r = findRight(bag, j, price[i]); // 找到行囊j中宝石的最右边位置
for (int p = l; p <= r; p++) { // [l,r]之间的宝石全部放入行囊j中
bag[p] = j;
}
capacity[j] -= r - l + 1; // 更新行囊j的容量
i--; // 处理下一个宝石
}
}
return true;
}
// 找到下一个可以放入宝石的行囊编号
private int findNext(int[] bag, int p) {
int n = bag.length;
int i = 0;
while (i < n && (bag[i] != -1 || (i > 0 && bag[i - 1] == -1 && p - i < i - 1))) {
i++;
}
return (i == n ? -1 : i);
}
// 找到上一个可用的行囊编号
private int findPrev(int[] bag, int j) {
int i = j - 1;
while (i >= 0 && bag[i] == -1) {
i--;
}
return i;
}
// 找到行囊j中宝石的最左边位置
private int findLeft(int[] bag, int j, int p) {
int i = j;
while (i >= 0 && bag[i] == j && p - i <= j - i) {
i--;
}
return i + 1;
}
// 找到行囊j中宝石的最右边位置
private int findRight(int[] bag, int j, int p) {
int n = bag.length;
int i = j;
while (i < n && bag[i] == j && i - p <= j - i) {
i++;
}
return i - 1;
}
@Test
public void test() {
int[] nums = {2, 3,5,4};
int n = 3;
System.out.println(maxScore1(nums, n));
}
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
public int maxScore1(int[] price, int k) {
backtracking(price, 0, k-1, 0);
return max - min;
}
public void backtracking(int[] price, int startIndex, int k, int cur) {
if (k == 0) {
cur += price[price.length - 1] + price[startIndex];
if (max < cur) max = cur;
if (min > cur) min = cur;
return;
}
for (int i = startIndex; i < price.length-k; i++) {
cur += price[startIndex] + price[i];
backtracking(price, i + 1, k - 1, cur);
cur -= price[startIndex] + price[i];
}
}
public static int shortestPath(int[][] maze, int startRow, int startCol, int endRow, int endCol) {
int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
Queue<int[]> queue = new LinkedList<>();
Set<String> visited = new HashSet<>();
queue.offer(new int[]{startRow, startCol, 0});
visited.add(startRow + "," + startCol);
while (!queue.isEmpty()) {
int[] pos = queue.poll();
int row = pos[0], col = pos[1], steps = pos[2];
if (row == endRow && col == endCol) {
return steps;
}
for (int[] d : directions) {
int newRow = row + d[0], newCol = col + d[1];
if (newRow >= 0 && newRow < maze.length && newCol >= 0 && newCol < maze[0].length
&& !visited.contains(newRow + "," + newCol) && maze[newRow][newCol] == 1) {
queue.offer(new int[]{newRow, newCol, steps + 1});
visited.add(newRow + "," + newCol);
}
}
}
return -1;
}
public static void main(String[] args) {
int[][] maze = {{1, 1, 1, 0, 1},
{1, 0, 1, 1, 1},
{1, 1, 1, 0, 1},
{0, 0, 1, 1, 1},
{1, 0, 0, 0, 1}};
int startRow = 0, startCol = 0, endRow = 4, endCol = 4;
System.out.println(shortestPath(maze, startRow, startCol, endRow, endCol)); // 输出4
}
}

View File

@ -0,0 +1,70 @@
package com.markilue.leecode.test;
import org.junit.Test;
import java.util.Arrays;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.test
*@Author: markilue
*@CreateTime: 2023-04-23 13:39
*@Description: TODO
*@Version: 1.0
*/
public class HeapSort {
@Test
public void test() {
int[] nums = {8, 6, 9, 1, 4, 7, 2, 3, 5};
heapSort(nums);
System.out.println(Arrays.toString(nums));
}
public void heapSort(int[] nums) {
int n = nums.length;
//从最后一个非叶子节点开始堆化
for (int i = n / 2 - 1; i >= 0; i--) {
adjustHeap(nums, i, n);
}
int temp;
//挨个取出重新堆化
for (int i = n - 1; i > 0; i--) {
temp = nums[i];
nums[i] = nums[0];
nums[0] = temp;
adjustHeap(nums, 0, i);
}
}
/**
*
* @param nums
* @param i 开始调整的位置
* @param length 长度
*/
public void adjustHeap(int[] nums, int i, int length) {
int root = nums[i];
for (int j = 2 * i + 1; j < length; j = 2 * j + 1) {
if (j + 1 < length && nums[j] < nums[j + 1]) {
j++;
}
if (root < nums[j]) {
nums[i] = nums[j];
i = j;
} else {
break;
}
}
nums[i] = root;//放到合适位置
}
}