力扣爆刷第173天之TOP200五连刷131-135(颜色分类、螺旋矩阵、零钱兑换)
文章目录
一、26. 删除有序数组中的重复项
题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/
思路:本题让删除有序数组中的重复项,所有重复的元素只保留一个,最后返回删除后剩余元素的个数,也是很经典的题目了。
1、首先明确一下,数组类型的题目,基本的操作手段一般就是双指针、快慢指针。
2、维护快慢指针,快指针正常遍历,只要遇到当前元素与前一个元素不等,就同步赋值给慢指针指向的位置;
3、当前元素与前一个元素相等不做处理。
这样遍历结束就完成了去重。最主要的思想就是不等元素同步覆盖,相等元素等待覆盖。
class Solution {
public int removeDuplicates(int[] nums) {
int k = 1;
for(int i = 1; i < nums.length; i++) {
if(nums[i-1] != nums[i]) {
nums[k++] = nums[i];
}
}
return k;
}
}
二、LCR 174. 寻找二叉搜索树中的目标节点
题目链接:https://leetcode.cn/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/description/
思路:本题让在二叉搜索树中寻找第K大的节点,其实很简单。
1、提到了二叉搜素树,那就应该想到二叉搜索树的特性,中序遍历为升序。
2、一般人只能想到这一点,可以如果稍微再变通一下就可以想到,逆序的中序遍历结果为降序。
3、本题正好可以利用这一点,维护两个全局变量,一个是K表示第几大的数,一个是res表示结果。
4、使用逆序的中序遍历进行遍历,先右再中再左,每次遍历到中间节点总的计数器就减一,减到0即可返回。
class Solution {
int res = -1, n = -1;
public int findTargetNode(TreeNode root, int cnt) {
n = cnt;
traverse(root);
return res;
}
void traverse(TreeNode root) {
if(root == null || n == 0) return;
traverse(root.right);
if(--n == 0) {
res = root.val;
return;
}
traverse(root.left);
}
}
三、75. 颜色分类
题目链接:https://leetcode.cn/problems/sort-colors/description/
思路:这道题的意思是有一个数组,数组中只存在0、1、2,让排序,其实思想和今天做的第1题是类似的。
1、首先明确一点,有三个数让排序,同时考虑三个数一起操作,是比较复杂的,复杂的问题往往需要分解。
2、再次明确一点,对于数组的题目,看到了以后先从双指针的角度进行考虑。
3、我们可以先对0进行排序,然后再对1进行排序,0和1排序完成后,剩下的就都是2。
4、至于如何排序,可以采用双指针,快指针往前遍历,慢指针负责和快指针交换0或者交换1即可。
class Solution {
public void sortColors(int[] nums) {
int zero = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 0) {
int temp = nums[i];
nums[i] = nums[zero];
nums[zero++] = temp;
}
}
int one = zero;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 1) {
int temp = nums[i];
nums[i] = nums[one];
nums[one++] = temp;
}
}
}
}
四、59. 螺旋矩阵 II
题目链接:https://leetcode.cn/problems/spiral-matrix-ii/description/
思路:给一个数N,让构造出一个螺旋矩阵。
1、思路很简单,只要模拟这个螺旋的运行轨迹就可以。
2、关键点在于如何模拟。
3、其实只需要维护好上下左右四个边界,当上与下之间有间隙时就可以左右遍历,当左与右之间有间隙时就可以上下遍历,每次遍历完了之后收缩边界即可。
class Solution {
public int[][] generateMatrix(int n) {
int[][] nums = new int[n][n];
int left = 0, right = n, up = 0, down = n, k = 1;
while(k <= n*n) {
if(up < down) {
for(int i = left; i < right; i++) nums[up][i] = k++;
up++;
}
if(left < right) {
for(int i = up; i < down; i++) nums[i][right-1] = k++;
right--;
}
if(up < down) {
for(int i = right-1; i >= left; i--) nums[down-1][i] = k++;
down--;
}
if(left < right) {
for(int i = down-1; i >= up; i--) nums[i][left] = k++;
left++;
}
}
return nums;
}
}
五、518. 零钱兑换 II
题目链接:https://leetcode.cn/problems/coin-change-ii/description/
思路:本题是完全背包求组合数问题。
心法如下:
1、完全背包的话,物品和背包都要正序。
2、完全背包求组合数,物品在外,背包在内。
3、完全背包求排列数,背包在内,物品在外。
class Solution {
public int change(int amount, int[] coins) {
int[] dp = new int[amount+1];
dp[0] = 1;
for(int i = 0; i < coins.length; i++) {
for(int j = coins[i]; j <= amount; j++) {
dp[j] += dp[j - coins[i]];
}
}
return dp[amount];
}
}