diff --git a/src/main/java/greedy/CanCompleteCircuit.java b/src/main/java/greedy/CanCompleteCircuit.java new file mode 100644 index 0000000..c32cd8a --- /dev/null +++ b/src/main/java/greedy/CanCompleteCircuit.java @@ -0,0 +1,78 @@ +package greedy; +/** + * 题目: 134. 加油站 (canCompleteCircuit) + * 描述:在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 + * 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 + * 给定两个整数数组 gas 和 cost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。 + * + * 示例 1: + 输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2] + 输出: 3 + 解释: + 从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油 + 开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油 + 开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油 + 开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油 + 开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油 + 开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。 + 因此,3 可为起始索引。 + + * 链接:https://leetcode.cn/problems/gas-station/ + */ +public class CanCompleteCircuit { + public int canCompleteCircuit1(int[] gas, int[] cost) { + int sumgas=0,sumcost=0; + int[] diff=new int[gas.length]; + for (int i = 0; i < gas.length; i++) { + sumgas+=gas[i]; + sumcost+=cost[i]; + diff[i]=gas[i]-cost[i]; + } + if(sumcost>sumgas) + return -1; + for (int i = 0; i < diff.length; i++) { + if(diff[i]>=0){ + int j=(i+1)%diff.length; + int cur=diff[i]; + boolean flag=true; + while(j!=i){ + cur+=diff[j]; + if(cur<0) { + flag=false; + break; + } + j=(j+1)%diff.length; + } + if(flag) + return i; + } + } + return -1; + } + public int canCompleteCircuit(int[] gas, int[] cost) { + int total = 0; // 总盈余:记录所有加油站油量差值的总和 + int tank = 0; // 当前油箱剩余:当前起点下的油量累计 + int start = 0; // 起始加油站索引 + + // 遍历所有加油站 + for (int i = 0; i < gas.length; i++) { + // 当前加油站的油量差值:加油量 - 行驶消耗 + int diff = gas[i] - cost[i]; + // 累计总盈余 + total += diff; + // 当前油箱剩余更新 + tank += diff; + + // 如果在当前起点,从起点到 i 的累计油量不足以到达 i+1, + // 那么必然不能从该起点出发完成环路,所以把起点更新为 i+1, + // 并且重置当前油箱剩余为 0 + if (tank < 0) { + start = i + 1; + tank = 0; + } + } + + // 如果总盈余小于 0,说明全局油量不足,返回 -1;否则返回更新后的起点 + return total < 0 ? -1 : start; + } +} diff --git a/src/main/java/greedy/CanJump.java b/src/main/java/greedy/CanJump.java new file mode 100644 index 0000000..8342c26 --- /dev/null +++ b/src/main/java/greedy/CanJump.java @@ -0,0 +1,58 @@ +package greedy; + +import java.util.Arrays; + +/** + * 题目: 55. 跳跃游戏 (canJump) + * 描述:给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 + * 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 + + * 示例 1: + 输入:nums = [2,3,1,1,4] + 输出:true + 解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。 + + * 链接:https://leetcode.cn/problems/jump-game/ + */ +public class CanJump { + //接近超时!记忆化搜索,记录每一个状态(这里是索引 i)是否能成功跳到最后。 + public boolean canJump1(int[] nums) { + // -1 表示未计算,0 表示不能到达,1 表示能到达 + int[] memo = new int[nums.length]; + Arrays.fill(memo, -1); + return helper(nums, 0, memo); + } + + boolean helper(int[] nums, int i, int[] memo) { + if (i >= nums.length - 1) return true; + if (memo[i] != -1) return memo[i] == 1; //-1代表没访问过,0代表失败,1代表成功 + + int max = nums[i]; + for (int j = 1; j <= max; j++) { + if (helper(nums, i + j, memo)) { + memo[i] = 1; + return true; + } + } + memo[i] = 0; //尝试了所有从当前位置 i 开始能跳的范围后,都没有跳到终点,说明从 i 出发是失败的。 + return false; + } + //太妙了! + public boolean canJump(int[] nums) { + int maxReach = 0; // 表示当前能到达的最远位置 + for (int i = 0; i < nums.length; i++) { + // 如果当前位置超过了当前能到达的最远位置,则无法到达该位置,返回 false + if (i > maxReach) { + return false; + } + // 更新当前能到达的最远位置 + maxReach = Math.max(maxReach, i + nums[i]); + // 如果能到达最后一个位置,则返回 true + if (maxReach >= nums.length - 1) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/greedy/Candy.java b/src/main/java/greedy/Candy.java new file mode 100644 index 0000000..9250a1c --- /dev/null +++ b/src/main/java/greedy/Candy.java @@ -0,0 +1,51 @@ +package greedy; +/** + * 题目: 135. 分发糖果 (candy) + * 描述:n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 + * 你需要按照以下要求,给这些孩子分发糖果: + * 每个孩子至少分配到 1 个糖果。 + * 相邻两个孩子评分更高的孩子会获得更多的糖果。 + * 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。 + + 示例 2: + 输入:ratings = [1,2,2] + 输出:4 + 解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。 + 第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。 + + * 链接:https://leetcode.cn/problems/candy/ + */ +//没想到,想复杂了 +public class Candy { + public int candy(int[] ratings) { + int n = ratings.length; + int[] candies = new int[n]; + + // 第一步:初始化每个孩子至少1颗糖果 + for (int i = 0; i < n; i++) { + candies[i] = 1; + } + + // 第二步:从左到右遍历,如果右侧评分高,给右侧多1颗 + for (int i = 1; i < n; i++) { + if (ratings[i] > ratings[i - 1]) { + candies[i] = candies[i - 1] + 1; + } + } + + // 第三步:从右到左遍历,如果左侧评分高,确保左侧孩子糖果更多 + for (int i = n - 2; i >= 0; i--) { + if (ratings[i] > ratings[i + 1]) { + candies[i] = Math.max(candies[i], candies[i + 1] + 1); + } + } + + // 求出总糖果数 + int sum = 0; + for (int candy : candies) { + sum += candy; + } + + return sum; + } +} diff --git a/src/main/java/greedy/FindMinArrowShots.java b/src/main/java/greedy/FindMinArrowShots.java new file mode 100644 index 0000000..749d575 --- /dev/null +++ b/src/main/java/greedy/FindMinArrowShots.java @@ -0,0 +1,34 @@ +package greedy; + +import java.util.Arrays; +import java.util.HashMap; + +/** + * 题目: 452. 用最少数量的箭引爆气球 (findMinArrowShots) + * 描述:有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 + * 一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。 + * 给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。 + + 示例 2: + 输入:points = [[10,16],[2,8],[1,6],[7,12]] + 输出:2 + 解释:气球可以用2支箭来爆破: + -在x = 6处射出箭,击破气球[2,8]和[1,6]。 + -在x = 11处发射箭,击破气球[10,16]和[7,12]。 + + * 链接:https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/ + */ +public class FindMinArrowShots { + public int findMinArrowShots(int[][] points) { + Arrays.sort(points, (a, b) -> Integer.compare(a[1], b[1])); + + int index=0,cnt=0; + while(index=points[index][0]) + index++; + cnt++; + } + return cnt; + } +} diff --git a/src/main/java/greedy/Jump.java b/src/main/java/greedy/Jump.java new file mode 100644 index 0000000..5a73da5 --- /dev/null +++ b/src/main/java/greedy/Jump.java @@ -0,0 +1,49 @@ +package greedy; + +/** + * 题目: 45. 跳跃游戏 II (jump) + * 描述:给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 + * 每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处: + * 0 <= j <= nums[i] + * i + j < n + * 返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。 + + * 示例 1: + 输入: nums = [2,3,1,1,4] + 输出: 2 + 解释: 跳到最后一个位置的最小跳跃数是 2。 + 从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。 + + * 链接:https://leetcode.cn/problems/jump-game-ii/ + */ + +//不会 https://programmercarl.com/0045.%E8%B7%B3%E8%B7%83%E6%B8%B8%E6%88%8FII.html#%E6%80%9D%E8%B7%AF +public class Jump { + //要从覆盖范围出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,覆盖范围一旦覆盖了终点,得到的就是最少步数! + public int jump(int[] nums) { + if (nums == null || nums.length == 0 || nums.length == 1) { + return 0; + } + //记录跳跃的次数 + int count=0; + //当前的覆盖最大区域 + int curDistance = 0; + //最大的覆盖区域 + int maxDistance = 0; + for (int i = 0; i < nums.length; i++) { + //在可覆盖区域内更新最大的覆盖区域 + maxDistance = Math.max(maxDistance,i+nums[i]); + //说明当前一步,再跳一步就到达了末尾 + if (maxDistance>=nums.length-1){ + count++; + break; + } + //遍历到当前覆盖的最大区域时,更新下一步可达的最大区域 + if (i==curDistance){ + curDistance = maxDistance; + count++; + } + } + return count; + } +} diff --git a/src/main/java/greedy/LargestSumAfterKNegations.java b/src/main/java/greedy/LargestSumAfterKNegations.java new file mode 100644 index 0000000..3b05e37 --- /dev/null +++ b/src/main/java/greedy/LargestSumAfterKNegations.java @@ -0,0 +1,48 @@ +package greedy; + +import java.util.Arrays; + +/** + * 题目: 1005. K 次取反后最大化的数组和 (largestSumAfterKNegations) + * 描述:给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组: + * 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 + * 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 + * 以这种方式修改数组后,返回数组 可能的最大和 。 + * + * 示例 1: + 输入:nums = [4,2,3], k = 1 + 输出:5 + 解释:选择下标 1 ,nums 变为 [4,-2,3] 。 + + * 链接:https://leetcode.cn/problems/maximize-sum-of-array-after-k-negations/ + */ +//有点绕 +public class LargestSumAfterKNegations { + //让绝对值大的负数变为正数,当前数值达到最大 那么如果将负数都转变为正数了,K依然大于0 只找数值最小的正整数进行反转 + public int largestSumAfterKNegations(int[] nums, int k) { + if (nums.length == 1) return nums[0]; + + // 排序:先把负数处理了 + Arrays.sort(nums); + + for (int i = 0; i < nums.length && k > 0; i++) { // 贪心点, 通过负转正, 消耗尽可能多的k + if (nums[i] < 0) { + nums[i] = -nums[i]; + k--; + } + } + + // 退出循环, k > 0 || k < 0 (k消耗完了不用讨论) + if (k % 2 == 1) { // k > 0 && k is odd:对于负数:负-正-负-正 + Arrays.sort(nums); // 再次排序得到最小的正数 + nums[0] = -nums[0]; + } + // k > 0 && k is even,flip数字不会产生影响: 对于负数: 负-正-负;对于正数:正-负-正 + + int sum = 0; + for (int num : nums) { // 计算最大和 + sum += num; + } + return sum; + } +} diff --git a/src/main/java/greedy/LemonadeChange.java b/src/main/java/greedy/LemonadeChange.java new file mode 100644 index 0000000..e2da4a1 --- /dev/null +++ b/src/main/java/greedy/LemonadeChange.java @@ -0,0 +1,68 @@ +package greedy; + +import java.util.ArrayList; +import java.util.List; + +/** + * 题目: 860. 柠檬水找零 (lemonadeChange) + * 描述:在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。 + * 每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。 + * 注意,一开始你手头没有任何零钱。 + * 给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。 + * + * 示例 1: + 输入:bills = [5,5,5,10,20] + 输出:true + 解释: + 前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。 + 第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。 + 第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。 + 由于所有客户都得到了正确的找零,所以我们输出 true。 + + * 链接:https://leetcode.cn/problems/lemonade-change/ + */ +public class LemonadeChange { + public boolean lemonadeChange(int[] bills) { + int five = 0; // 记录 5 美元的数量 + int ten = 0; // 记录 10 美元的数量 + + // 遍历每一笔账单 + for (int bill : bills) { + switch (bill) { + case 5: + // 收到 5 美元,不需找零 + five++; + break; + + case 10: + // 收到 10 美元,需要找回 5 美元 + if (five > 0) { + five--; // 找回一张 5 美元 + ten++; // 保存这张 10 美元 + } else { + return false; + } + break; + + case 20: + // 收到 20 美元,需要找回 15 美元 + // 优先使用一张 10 美元和一张 5 美元找零 + if (ten > 0 && five > 0) { + ten--; + five--; + } + // 如果没有 10 美元,则用三张 5 美元找零 + else if (five >= 3) { + five -= 3; + } else { + return false; + } + break; + + default: + return false; + } + } + return true; + } +} diff --git a/src/main/java/greedy/MaxProfit.java b/src/main/java/greedy/MaxProfit.java index 383c5bc..078f07d 100644 --- a/src/main/java/greedy/MaxProfit.java +++ b/src/main/java/greedy/MaxProfit.java @@ -1,9 +1,5 @@ package greedy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - /** * 题目: 121. 买卖股票的最佳时机 (maxProfit) * 描述:给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 @@ -18,8 +14,7 @@ import java.util.List; * 链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/ */ -//第一道贪心,学思路 - //每次都假设是今天卖出,然后求今天之前的历史最低点。 + //第一次做没想出来,每次都假设是今天卖出,然后求今天之前的历史最低点。 public class MaxProfit { public int maxProfit(int prices[]) { int minprice = Integer.MAX_VALUE; @@ -27,7 +22,7 @@ public class MaxProfit { for (int price : prices) { if (price < minprice) { minprice = price; - } else if (price - minprice > maxprofit) { + } else if (price - minprice > maxprofit) { //else if 是因为今日如果买进,今日卖出收益为0 maxprofit = price - minprice; } } diff --git a/src/main/java/greedy/MaxProfit2.java b/src/main/java/greedy/MaxProfit2.java new file mode 100644 index 0000000..5106975 --- /dev/null +++ b/src/main/java/greedy/MaxProfit2.java @@ -0,0 +1,49 @@ +package greedy; +/** + * 题目: 122. 买卖股票的最佳时机 II (maxProfit) + * 描述:给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。 + * 在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。 + * 返回 你能获得的 最大 利润 。 + + * 示例 1: + 输入:prices = [7,1,5,3,6,4] + 输出:7 + 解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。 + 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。 + 最大总利润为 4 + 3 = 7 。 + + * 链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/ + */ +//考虑复杂了! +public class MaxProfit2 { + public int maxProfit1(int[] prices) { + int prediff=0,curdiff=0,maxprofit=0,buyprice=0; + boolean flag=false; + for (int i = 1; i < prices.length; i++) { + curdiff=prices[i]-prices[i-1]; + if(!flag){ + if(prediff<=0 &&curdiff>0){ + flag=true; + buyprice=prices[i-1]; + } + }else { + if(prediff>=0&&curdiff<0){ + flag=false; + maxprofit+=prices[i-1]-buyprice; + } + } + prediff=curdiff; + } + if(flag) + maxprofit+=prices[prices.length-1]-buyprice; + return maxprofit; + } + //收集正利润的区间,就是股票买卖的区间,而我们只需要关注最终利润,不需要记录区间。 + public int maxProfit(int[] prices) { + int result = 0; + for (int i = 1; i < prices.length; i++) { + result += Math.max(prices[i] - prices[i - 1], 0); + } + return result; + } +} diff --git a/src/main/java/greedy/PartitionLabels.java b/src/main/java/greedy/PartitionLabels.java new file mode 100644 index 0000000..454a237 --- /dev/null +++ b/src/main/java/greedy/PartitionLabels.java @@ -0,0 +1,88 @@ +package greedy; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * 题目: 763. 划分字母区间 (partitionLabels) + * 描述:给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。例如,字符串 "ababcc" 能够被分为 ["abab", "cc"],但类似 ["aba", "bcc"] 或 ["ab", "ab", "cc"] 的划分是非法的。 + * 注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。 + * 返回一个表示每个字符串片段的长度的列表。 + + 示例 2: + 输入:s = "ababcbacadefegdehijhklij" + 输出:[9,7,8] + 解释: + 划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。 + 每个字母最多出现在一个片段中。 + 像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。 + + * 链接:https://leetcode.cn/problems/partition-labels/ + */ +public class PartitionLabels { + /** + * 可以通过,但是时间复杂度高! + 预先计算字符最后出现位置 + 一种常见且高效的做法是在遍历字符串前,用一个 Map 或者数组记录下每个字符的最后出现索引。这样,在后续遍历时,能够通过字符直接查到其最后出现位置,避免重复扫描。 + + 维护当前区间右边界 + 在遍历过程中,维护一个 end 变量表示当前区间内所有字符最后出现位置的最大值。每遇到一个新的字符,就更新 end = Math.max(end, lastIndex[当前字符])。当遍历索引等于 end 时,说明当前区间已经完整,可以结束分区并记录长度。 + + 简化逻辑避免重复循环 + 采用上述方法后,代码只需要一次遍历即可确定所有分区长度,无需额外遍历区间内所有字符进行检查。 + */ + public List partitionLabels1(String s) { + HashMapmap=new HashMap<>(); + Listlist=new ArrayList<>(); + for (int i = 0; i < s.length(); i++) { + map.put(s.charAt(i),map.getOrDefault(s.charAt(i),0)+1); + } + StringBuffer buffer=new StringBuffer(); + for (int i = 0; i < s.length(); i++) { + boolean flag=true; + char cur=s.charAt(i); + buffer.append(cur); + int newCount = map.get(cur) - 1; + if (newCount > 0) { + map.put(cur, newCount); + } else { + map.remove(cur); + } + for (int j = 0; j < buffer.length(); j++) { + if (map.containsKey(buffer.charAt(j))) { + flag = false; + break; + } + } + if(flag) { + list.add(buffer.length()); + buffer.setLength(0); + } + } + return list; + } + //看这个 + public List partitionLabels(String s) { + // 用于记录每个字符最后一次出现的索引 + HashMap lastOccurrence = new HashMap<>(); + for (int i = 0; i < s.length(); i++) { + lastOccurrence.put(s.charAt(i), i); + } + + List partitionSizes = new ArrayList<>(); + int start = 0, end = 0; // start 记录当前分区开始的位置 + + for (int i = 0; i < s.length(); i++) { + // 更新当前分区的最远截止位置 + end = Math.max(end, lastOccurrence.get(s.charAt(i))); + // 当遍历到分区的最远截止位置时,说明可以划分一个区间 + if (i == end) { + partitionSizes.add(end - start + 1); + start = i + 1; // 下一分区的起始位置 + } + } + + return partitionSizes; + } +} diff --git a/src/main/java/greedy/ReconstructQueue.java b/src/main/java/greedy/ReconstructQueue.java new file mode 100644 index 0000000..990b7ad --- /dev/null +++ b/src/main/java/greedy/ReconstructQueue.java @@ -0,0 +1,41 @@ +package greedy; + +import java.util.Arrays; +import java.util.LinkedList; + +/** + * 题目: 406. 根据身高重建队列 II (maxProfit) + * 描述:假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。 + * 请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。 + + * 示例 1: + 输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]] + 输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] + 解释: + 编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。 + 编号为 1 的人身高为 7 ,没有身高更高或者相同的人排在他前面。 + 编号为 2 的人身高为 5 ,有 2 个身高更高或者相同的人排在他前面,即编号为 0 和 1 的人。 + 编号为 3 的人身高为 6 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。 + 编号为 4 的人身高为 4 ,有 4 个身高更高或者相同的人排在他前面,即编号为 0、1、2、3 的人。 + 编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。 + 因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。 + + * 链接:https://leetcode.cn/problems/queue-reconstruction-by-height/ + */ +//不会 ,很妙 +public class ReconstructQueue { + public int[][] reconstructQueue(int[][] people) { + // 身高从大到小排(身高相同k小的站前面) + Arrays.sort(people, (a, b) -> { + if (a[0] == b[0]) return a[1] - b[1]; // a - b 是升序排列,故在a[0] == b[0]的狀況下,會根據k值升序排列 + return b[0] - a[0]; //b - a 是降序排列,在a[0] != b[0],的狀況會根據h值降序排列 + }); + + LinkedList que = new LinkedList<>(); + for (int[] p : people) { + que.add(p[1],p); //Linkedlist.add(index, value),會將value插入到指定index裡。 + } + + return que.toArray(new int[people.length][]); + } +} diff --git a/src/test/java/greedy/CanCompleteCircuitTest.java b/src/test/java/greedy/CanCompleteCircuitTest.java new file mode 100644 index 0000000..d5cd08c --- /dev/null +++ b/src/test/java/greedy/CanCompleteCircuitTest.java @@ -0,0 +1,16 @@ +package greedy; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class CanCompleteCircuitTest { + + @Test + public void canCompleteCircuit() { + int[] gas = {1,2,3,4,5}, cost = {3,4,5,1,2}; + CanCompleteCircuit solution = new CanCompleteCircuit(); + int res=solution.canCompleteCircuit(gas,cost); + System.out.println(res); + } +} \ No newline at end of file diff --git a/src/test/java/greedy/FindMinArrowShotsTest.java b/src/test/java/greedy/FindMinArrowShotsTest.java new file mode 100644 index 0000000..60b1120 --- /dev/null +++ b/src/test/java/greedy/FindMinArrowShotsTest.java @@ -0,0 +1,18 @@ +package greedy; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class FindMinArrowShotsTest { + + @Test + public void findMinArrowShots() { +// int[][] points = {{10,16},{2,8},{1,6},{7,12}}; +// int[][] points ={{1,2},{3,4},{4,5},{2,3}}; + int[][] points = {{-2147483646,-2147483645},{2147483646,2147483647}}; + FindMinArrowShots solution = new FindMinArrowShots(); + int res=solution.findMinArrowShots(points); + System.out.println(res); + } +} \ No newline at end of file diff --git a/src/test/java/greedy/JumpTest.java b/src/test/java/greedy/JumpTest.java new file mode 100644 index 0000000..4997adc --- /dev/null +++ b/src/test/java/greedy/JumpTest.java @@ -0,0 +1,16 @@ +package greedy; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class JumpTest { + + @Test + public void jump() { + int[] nums = new int[]{2,2,1,2,4}; + Jump solution = new Jump(); + int res=solution.jump(nums); + System.out.println(res); + } +} \ No newline at end of file diff --git a/src/test/java/greedy/MaxProfit2Test.java b/src/test/java/greedy/MaxProfit2Test.java new file mode 100644 index 0000000..3c9a40f --- /dev/null +++ b/src/test/java/greedy/MaxProfit2Test.java @@ -0,0 +1,16 @@ +package greedy; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class MaxProfit2Test { + + @Test + public void maxProfit() { + int[]prices = {1,2,3,4,5}; + MaxProfit2 solution = new MaxProfit2(); + int res=solution.maxProfit(prices); + System.out.println(res); + } +} \ No newline at end of file