LC每日一题45. 跳跃游戏 II
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
示例:
输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
说明:
假设你总是可以到达数组的最后一个位置。
解题思路
dp[i]代表到i的最少跳跃次数,复杂度O(n^2),穷举了0-length-1每个坐标可能到的地方,同时优化了一下对于当前i来说,i-1能跳到的坐标就不做操作了
代码1 O(n^2)
class Solution {
public int jump(int[] nums) {
if(nums==null||nums.length<2)return 0;
int[] dp=new int[nums.length];
Arrays.fill(dp,Integer.MAX_VALUE-1);
dp[0]=0;
for(int i=0;i<nums.length-1;i++){
for(int j=i+1;j<=i+nums[i];j++){
if(j<nums.length){
if(i!=0&&j<=i-1+nums[i-1])continue;
dp[j]=Math.min(dp[j],dp[i]+1);
}
}
}
return dp[nums.length-1];
}
}
代码2 贪心,每次跳最远
class Solution {
public int jump(int[] nums) {
if(nums==null||nums.length<2)return 0;
int max=0,end=nums[0],ans=0;
for(int i=0;i<nums.length-1;i++){
max=Math.max(i+nums[i],max);
if(i==end){
ans++;
end=max;
}
}
ans++;
return ans;
}
}
48. 旋转图像
解题思路
思路简单清晰,不管n单双,都旋转n/2次,设上下左右边界,从外向里依次旋转, 每次旋转只要交换三次即可
对于上边界,列是left到right-1
对于左边界,行是bot到top+1
对于下边界,列是right到left+1
要注意从哪里到哪里,方向不能错,当然也有其他的写法,但是大体思想就是顺时针
代码
class Solution {
public void rotate(int[][] matrix) {
if(matrix.length==1)return;
int top=0,bot=matrix.length-1,left=0,right=matrix.length-1;
for(int i=0;i<matrix.length/2;i++){
reverse(matrix,top,bot,left,right);
top++;bot--;left++;right--;
}
}
void reverse(int[][] matrix,int top,int bot,int left,int right){
for(int j=0;j<right-left;j++){
int tmp=matrix[top+j][right];//先保存有边界
matrix[top+j][right]=matrix[top][j+left];//上边界旋转到右边界
matrix[top][j+left]=matrix[bot-j][left];//左边旋转到上边
matrix[bot-j][left]=matrix[bot][right-j];//下边旋转到左边
matrix[bot][right-j]=tmp;//右边旋转到下边
}
}
}
406. 根据身高重建队列
解题思路
排序的时候每次先选最高的,如果一样高就选前面没人的,有点贪心的感觉。
插入的时候我们就直接根据排在前面有几个人索引的位置插入就行了,因为LinkedList结构,会自动后移,而且后插入相同位置的人个子比较矮,不影响前面已经插入的高个子
class Solution {
public int[][] reconstructQueue(int[][] people) {
Arrays.sort(people,(o1,o2)->o1[0]==o2[0]?o1[1]-o2[1]:o2[0]-o1[0]);
List<int[]> ans=new LinkedList<>();
for(int[] n:people)
ans.add(n[1],n);
return ans.toArray(people);
}
}