diff --git a/Leecode/src/main/java/com/markilue/leecode/greedy/T10_1_ReconstructQueue.java b/Leecode/src/main/java/com/markilue/leecode/greedy/T10_1_ReconstructQueue.java new file mode 100644 index 0000000..8cad6cb --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/greedy/T10_1_ReconstructQueue.java @@ -0,0 +1,148 @@ +package com.markilue.leecode.greedy; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.greedy + *@Author: markilue + *@CreateTime: 2023-02-10 11:01 + *@Description: + * TODO 力扣406题 根据身高重建队列: + * 假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。 + * 每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。 + * 请你重新构造并返回输入数组 people 所表示的队列。 + * 返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。 + *@Version: 1.0 + * + */ +public class T10_1_ReconstructQueue { + + @Test + public void test() { +// int[][] people = new int[][]{{7, 0}, {4, 4}, {7, 1}, {5, 0}, {6, 1}, {5, 2},{4,1}}; + int[][] people = new int[][]{{6, 0}, {5, 0}, {4, 0}, {3, 2}, {2, 2}, {1, 4}}; + reconstructQueue(people); + } + + + /** + * 思路:先升序排列一下,再反向腾挪位置 + * 速度击败78.37%,内存击败73.68% 6ms + * @param people + * @return + */ + public int[][] reconstructQueue(int[][] people) { + + //升序排列一下 + Arrays.sort(people, (array1, array2) -> { + return array1[0] != array2[0] ? array1[0] - array2[0] : array1[1] - array2[1]; + }); + + //反向遍历,挪位置 + for (int i = people.length - 1; i >= 0; i--) { + //统计前面有多少个相等的数,看看这个值与people[i][1]是否相等 + int count = 0; + for (int j = i - 1; j >= 0; j--) { + if (people[j][0] == people[i][0]) { + count++; + } else break; + } + //不等于就需要向后挪动 + if (people[i][1] != count) { + int[] cur = people[i]; + int index = people[i][1] - count; + if (i + index < people.length) { + System.arraycopy(people, i + 1, people, i, index); + people[i + index] = cur; + } + } + } + return people; + } + + + /** + * 代码随想录思路:本质上一致,就是分别考虑两个维度,想考虑身高,在考虑位置 + * 不过与本人不同的是:他是先由大到小排列,然后使用linkedList一个一个插入 + * 时间击败67.5% 内存击败47.51% 7ms + * @param people + * @return + */ + public int[][] reconstructQueue1(int[][] people) { + // 身高从大到小排(身高相同k小的站前面) + Arrays.sort(people, (a, b) -> { + if (a[0] == b[0]) return a[1] - b[1]; + return b[0] - a[0]; + }); + + LinkedList que = new LinkedList<>(); + + for (int[] p : people) { + que.add(p[1],p); + } + + return que.toArray(new int[people.length][]); + } + + + /** + * 官方最快:2ms + * 本质上只是自己实现了快排来进行排序 + * @param people + * @return + */ + public int[][] reconstructQueue2(int[][] people) { + int len = people.length; + quickSort(people, 0, len - 1); + List ans = new ArrayList(); + for (int[] person : people) { + ans.add(person[1], person); + } + return ans.toArray(new int[ans.size()][]); + } + + private void quickSort(int[][] array, int left, int right){ + if(left >= right){ + return; + } + int i = left, j = right; + int[] temp = array[left]; + int index = left; + while(i < j){ + while(i < j && compareValue1(array[i], temp)){ + i++; + } + while(i < j && !compareValue1(array[j], temp)){ + j--; + } + if(i < j){ + int[] t = array[i]; + array[i] = array[j]; + array[j] = t; + } + if(array[i] == temp){ + index = i; + }else if(array[j] == temp){ + index = j; + } + } + array[index] = array[i]; + array[i] = temp; + quickSort(array, left, i - 1); + quickSort(array, i + 1, right); + } + + private boolean compareValue1(int[] a, int[] b){ + if(a[0] == b[0]){ + return a[1] < b[1]; + }else{ + return a[0] > b[0]; + } + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/greedy/LemonadeChange.java b/Leecode/src/main/java/com/markilue/leecode/greedy/T10_LemonadeChange.java similarity index 99% rename from Leecode/src/main/java/com/markilue/leecode/greedy/LemonadeChange.java rename to Leecode/src/main/java/com/markilue/leecode/greedy/T10_LemonadeChange.java index cf617e0..839a7b1 100644 --- a/Leecode/src/main/java/com/markilue/leecode/greedy/LemonadeChange.java +++ b/Leecode/src/main/java/com/markilue/leecode/greedy/T10_LemonadeChange.java @@ -17,7 +17,7 @@ import java.util.HashMap; * 给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。 * @Version: 1.0 */ -public class LemonadeChange { +public class T10_LemonadeChange { @Test public void test(){ diff --git a/Leecode/src/main/java/com/markilue/leecode/greedy/second/T09_Candy.java b/Leecode/src/main/java/com/markilue/leecode/greedy/second/T09_Candy.java index baa1075..c041186 100644 --- a/Leecode/src/main/java/com/markilue/leecode/greedy/second/T09_Candy.java +++ b/Leecode/src/main/java/com/markilue/leecode/greedy/second/T09_Candy.java @@ -1,5 +1,9 @@ package com.markilue.leecode.greedy.second; +import org.junit.Test; + +import java.util.Arrays; + /** *@BelongsProject: Leecode *@BelongsPackage: com.markilue.leecode.greedy.second @@ -16,7 +20,47 @@ package com.markilue.leecode.greedy.second; */ public class T09_Candy { + @Test + public void test() { + int[] ratings = {1, 0, 2}; + System.out.println(candy(ratings)); + } + + /** + * 思路:需要知道左右分别需要这个位置最少是多少,然后两者中取大,两次贪心 + * 本质上不算我过得,还有有点印象看过答案 + * 速度击败98.68% 内存击败58% + * @param ratings + * @return + */ public int candy(int[] ratings) { + int[] leftMin = new int[ratings.length]; + + leftMin[0] = 1; + //记录左边递增序列,每个位置最少需要多少,向右贪心 + for (int i = 1; i < ratings.length; i++) { + if (ratings[i] > ratings[i - 1]) { + leftMin[i] = leftMin[i - 1] + 1; + }else { + leftMin[i]=1; + } + } + + int result = 0; + int lastNeed = 1; + //向左贪心,记录每个位置最少需要,加在总和里 + for (int i = ratings.length - 1; i >= 0; i--) { + + if (i != ratings.length - 1 && ratings[i] > ratings[i + 1]) { + lastNeed = lastNeed + 1; + } else { + lastNeed = 1; + } + result += Math.max(leftMin[i], lastNeed); + } + + return result; + } } diff --git a/Leecode/src/main/java/com/markilue/leecode/greedy/second/T10_LemonadeChange.java b/Leecode/src/main/java/com/markilue/leecode/greedy/second/T10_LemonadeChange.java new file mode 100644 index 0000000..a067a68 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/greedy/second/T10_LemonadeChange.java @@ -0,0 +1,50 @@ +package com.markilue.leecode.greedy.second; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.greedy.second + *@Author: markilue + *@CreateTime: 2023-02-10 10:47 + *@Description: + * TODO 力扣860 柠檬水找零: + * 在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。 + * 每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。 + * 注意,一开始你手头没有任何零钱。 + * 给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。 + *@Version: 1.0 + */ +public class T10_LemonadeChange { + + /** + * 思路:有大钱先用大钱,没大钱用小钱,因为小钱可以找开所有 + * @param bills + * @return + */ + public boolean lemonadeChange(int[] bills) { + int[] count = new int[3];//5,10,20的count + + for (int i = 0; i < bills.length; i++) { + if (bills[i] == 5) { + count[0]++; + continue; + } + + if(bills[i]==10){ + count[0]--; + count[1]++; + + }else { + //最难讨论的 + if(count[1]>0){ + count[1]--; + count[0]--; + }else { + count[0]-=3; + } + } + if(count[0]<0)return false; + } + return true; + + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/sort/QuickSort.java b/Leecode/src/main/java/com/markilue/leecode/sort/QuickSort.java new file mode 100644 index 0000000..9e0f029 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/sort/QuickSort.java @@ -0,0 +1,69 @@ +package com.markilue.leecode.sort; + +import org.junit.Test; + +import java.util.Arrays; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.sort + *@Author: markilue + *@CreateTime: 2023-02-10 12:18 + *@Description: TODO 自己实现快排: + *@Version: 1.0 + */ +public class QuickSort { + + @Test + public void test(){ + int[] nums={8,5,3,7,6,4,1,9}; + quickSort(nums,0,nums.length-1); + System.out.println(Arrays.toString(nums)); + } + + + public void quickSort(int[] nums, int left, int right) { + if(left>=right)return; + int mid = partition(nums, left, right); + quickSort(nums, left, mid - 1); + quickSort(nums, mid + 1, right); + } + + /** + * 寻找num[left]的合适的位置 + * @param nums + * @param left + * @param right + */ + public int partition(int[] nums, int left, int right) { + + if (left >= right) return left; + + int start = left + 1; + int end = right; + + while (start <= end) { + while (start < right && nums[start] < nums[left]) { + start++; + } + + while (end > left && nums[end] > nums[left]) { + end--; + } + if(start>=end)break; + //找到两个需要交换的值 + swap(nums, start, end); + start++; + end--; + + } + swap(nums, left, end); + return end; + } + + public void swap(int[] nums, int left, int right) { + int temp = nums[left]; + nums[left] = nums[right]; + nums[right] = temp; + } +}