diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T17_23_MergeKLists.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T17_23_MergeKLists.java new file mode 100644 index 0000000..72a8485 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T17_23_MergeKLists.java @@ -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; + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T18_31_NextPermutation.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T18_31_NextPermutation.java new file mode 100644 index 0000000..13f107a --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T18_31_NextPermutation.java @@ -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--; + } + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T19_32_LongestValidParentheses.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T19_32_LongestValidParentheses.java index d459ffa..6230265 100644 --- a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T19_32_LongestValidParentheses.java +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T19_32_LongestValidParentheses.java @@ -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 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; + + } } diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T20_33_Search.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T20_33_Search.java new file mode 100644 index 0000000..ceaccc8 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T20_33_Search.java @@ -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 在预先未知的某个下标 k(0 <= 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; + } + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T21_34_SearchRange.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T21_34_SearchRange.java new file mode 100644 index 0000000..42afb52 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T21_34_SearchRange.java @@ -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}; + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/second/T22_39_CombinationSum.java b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T22_39_CombinationSum.java new file mode 100644 index 0000000..9cd216c --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/second/T22_39_CombinationSum.java @@ -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 cur = new ArrayList<>(); + List> result = new ArrayList<>(); + + /** + * + * @param candidates + * @param target + * @return + */ + public List> 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); + } + + + } + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/interview/meituan/test1.java b/Leecode/src/main/java/com/markilue/leecode/interview/meituan/test1.java new file mode 100644 index 0000000..4560548 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/interview/meituan/test1.java @@ -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 queue = new LinkedList<>(); + Set 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 + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/test/HeapSort.java b/Leecode/src/main/java/com/markilue/leecode/test/HeapSort.java new file mode 100644 index 0000000..6f4d1bc --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/test/HeapSort.java @@ -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;//放到合适位置 + + + } +}