-
- 跳跃游戏 II
题目背景
给定一个非负整数数组 nums,你最初位于数组的第一个位置。每个元素代表你在该位置可以跳跃的最大长度。目标是使用最少的跳跃次数到达数组的最后一个位置。
实现思路
预处理:将每个位置的最大可到达位置进行预处理,存储在原数组中。
贪心策略:从当前位置出发,选择下一个能够到达最远位置的点作为下一个跳跃点。
终止条件:如果当前位置能够直接到达或越过终点,则返回当前步数。
代码逻辑
遍历数组,更新每个位置的最大可到达位置。
使用 while 循环,每次选择当前范围内能到达最远位置的点。
如果当前范围覆盖终点,则直接返回步数。
优化点
不需要修改原数组,可以在原数组上直接计算最大可到达位置,节省空间。
点击查看代码
//45. 跳跃游戏 IIpublic int jump(int[] nums) {if (nums.length == 0||nums.length == 1) return 0;for (int i = 0; i < nums.length; i++) {//统计每个位置最大能到达的右边界nums[i] = i +nums[i] ;}int count = 0;int left = 0;while (true) {if (nums[left] >= nums.length-1) {//判断右边界是否能够抵达终点,如果可以,就一步到位return ++count;}int max = left;for (int i = left+1; i <= nums[left]; i++) {//找到右边界最大的点if (nums[max]<nums[i]) max = i;}left = max;count++;}}
-
- 跳跃游戏
题目背景
判断是否能够通过跳跃到达数组的最后一个位置。
实现思路
贪心策略:维护一个变量 count,表示当前能到达的最远位置。
遍历数组:在遍历过程中,更新 count,如果 count 小于当前索引,则无法继续前进,返回 false。
代码逻辑
初始化 count 为 nums[0]。
遍历数组,更新 count 为当前能到达的最远位置。
如果 count 为 0,则返回 false;如果遍历完成,则返回 true。
优化点
代码中已经使用了较优的贪心策略,时间复杂度为 O(n)。
点击查看代码
//55. 跳跃游戏public boolean canJump(int[] nums) {//3ms/*if (nums == null || nums.length == 0||nums.length == 1) return true;if (nums[0]==0) return false;for (int i = 1; i < nums.length-1; i++) {nums[i] = Math.max(nums[i-1]-1,nums[i]);if (nums[i] == 0) return false;}return true;*///2msif (nums == null || nums.length == 0||nums.length == 1) return true;if (nums[0]==0) return false;int count=nums[0];for (int i = 1; i < nums.length-1; i++) {count = Math.max(count-1,nums[i]);if (count == 0) return false;}return true;}
-
- 买卖股票的最佳时机 II
题目背景
给定一个数组 prices,表示每天的股票价格。可以进行多次买卖,但不能同时参与多笔交易。目标是最大化利润。
实现思路
贪心策略:只要当前价格高于前一天价格,就进行一次买卖操作。
累加利润:将所有可能的正利润累加起来。
代码逻辑
使用双指针 i 和 j,分别表示前一天和当天。
如果当天价格高于前一天价格,则累加利润。
遍历完成后返回总利润。
优化点
当前实现已经很高效,时间复杂度为 O(n)。
点击查看代码
//122. 买卖股票的最佳时机 IIpublic int maxProfit2(int[] prices) {//实现1/*int maxProfit = 0;int i=0,j=0;for (int k = 1; k < prices.length; k++) {if (i<j&&prices[k]<prices[j]){//已有可盈利的购入股票日和售出日,当股价开始下降时,提前一天将其售出maxProfit+=prices[j]-prices[i];i=k;//将降价当天设定为购入日}if(prices[k] > prices[i]) {//更新售出日j=k;}else if(prices[k] <= prices[i]) {//找到购入日i=k;}}if(i<j) maxProfit+=prices[j]-prices[i];//检验股票是否有可盈利的购入股票日和售出日,如果有,则将其售出return maxProfit;*///贪心实现2if (prices == null || prices.length == 0) return 0;if (prices.length == 1) return prices[0];int sum = 0;int i=0,j=1;while (j < prices.length) {if (prices[j]-prices[i]>0) {//处理每一小段,只要有盈利就累加sum += prices[j]-prices[i];}i++;j++;}return sum;}
-
- 最大子数组和
题目背景
给定一个整数数组 nums,找到一个具有最大和的连续子数组。
实现思路
动态规划:使用 Kadane 算法,维护一个变量 currentSum 表示当前子数组的最大和,另一个变量 maxSum 表示全局最大和。
更新策略:如果 currentSum 小于 0,则丢弃当前子数组,重新开始。
代码逻辑
初始化 currentSum 和 maxSum 为数组的第一个元素。
遍历数组,更新 currentSum 和 maxSum。
返回 maxSum。
优化点
当前实现已经是最优解,时间复杂度为 O(n)。
点击查看代码
//53. 最大子数组和public int maxSubArray(int[] nums) {//暴力算法,超时/*if (nums == null || nums.length == 0) return 0;if (nums.length == 1) return nums[0];int maxSum = Integer.MIN_VALUE;for (int i = 0; i < nums.length; i++) {int sum = nums[i];maxSum = Math.max(maxSum, sum);for (int j = i + 1; j < nums.length; j++) {sum += nums[j];maxSum = Math.max(maxSum, sum);}}return maxSum;*/if (nums == null || nums.length == 0) return 0;if (nums.length == 1) return nums[0];int maxSum = nums[0]; // 初始化为数组的第一个元素int currentSum = nums[0]; // 当前子数组的最大和for (int i = 1; i < nums.length; i++) {// 如果当前子数组的和小于0,则重新开始一个新的子数组currentSum = Math.max(nums[i], currentSum + nums[i]);// 更新全局最大和maxSum = Math.max(maxSum, currentSum);}return maxSum;}
-
- 摆动序列
题目背景
给定一个整数数组 nums,定义一个摆动序列:相邻两个差值的符号必须相反。目标是找到最长的摆动子序列的长度。
实现思路
差值判断:计算相邻两个元素的差值,判断是否满足摆动条件。
状态更新:维护一个变量 prevDiff 表示前一个差值,用于判断当前差值是否与前一个差值异号。
代码逻辑
初始化 maxLength 为 1,prevDiff 为 0。
遍历数组,计算当前差值。
如果当前差值不为 0 且与前一个差值异号,则增加序列长度。
返回 maxLength。
优化点
当前实现已经很高效,时间复杂度为 O(n)。
点击查看代码
//376. 摆动序列public int wiggleMaxLength(int[] nums) {if (nums == null || nums.length == 0) return 0;if (nums.length == 1) return 1;int maxLength = 1; // 初始化为1,因为单个数字本身是一个摆动序列int prevDiff = 0; // 用于记录前一个差值for (int i = 1; i < nums.length; i++) {int currDiff = nums[i] - nums[i - 1]; // 当前差值if (currDiff != 0) { // 如果当前差值不为0if (prevDiff == 0 || currDiff * prevDiff < 0) { // 如果前一个差值为0(即i前面都是同一个数字),或者当前差值与前一个差值异号maxLength++; // 增加摆动序列的长度prevDiff = currDiff; // 更新前一个差值}}}return maxLength;}
-
- 分发饼干
题目背景
给定两个数组 g 和 s,分别表示孩子的胃口值和饼干的大小。目标是最大化满足孩子的数量。
实现思路
排序:对孩子的胃口值和饼干大小分别排序。
贪心策略:
策略一:优先满足胃口大的孩子,跳过因胃口太大而无法满足的孩子。
策略二:优先满足胃口小的孩子,跳过份量太小的饼干。
代码逻辑
对两个数组进行排序。
使用双指针遍历,根据策略选择匹配方式。
返回满足孩子的数量。
优化点
当前实现已经很高效,时间复杂度为 O(nlogn)(排序的开销)。
点击查看代码
//455. 分发饼干//大的饼干尽量分配给胃口大的孩子,跳过因胃口太大而不能满足的孩子public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int i = g.length-1, j = s.length-1;int count = 0;while (i >= 0 && j >= 0) {if (g[i]>s[j]){i--;}else {i--;j--;count++;}}return count;}//先满足胃口小的孩子,跳过份量太小的饼干/*public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int i = 0, j = 0;int count = 0;while (i < g.length && j< s.length) {if (g[i]>s[j]){j++;}else {i++;j++;count++;}}return count;}*/