#LeetCode 56. Merge Intervals
#LeetCode 56. 视频讲解:贪心算法,合并区间有细节!LeetCode:56.合并区间_哔哩哔哩_bilibili
依然是通过比较左边界来判断的是否重叠,如果第i 个数组的左边界小于第i - 1 个数组的右边界,则代表存在重叠的区间,但不会直接加入,因为可能有一种情况是:[1, 5] 和 [2, 3],所以记录下最新的右边界,继续比较。如果是不重叠区间,则直接存入list 数组。在存入的时候采用的方式是:list.add(new int[] {start, right}); 这样的形式通常被用做存储intervals 或者ranges。
在一些情况下,为了确保最后的边缘情况,会显式的再次添加当前的区间来防止边缘情况的发生。
代码:
class Solution {
public int[][] merge(int[][] intervals) {
List<int[]> list = new LinkedList<>();
Arrays.sort(intervals, (a, b) -> {
return Integer.compare(a[0], b[0]);
});
int start = intervals[0][0]; // left
int right = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] <= right) {
right = Math.max(right, intervals[i][1]);
} else {
list.add(new int[] {start, right});
start = intervals[i][0];
right = intervals[i][1];
}
}
list.add(new int[] {start, right});
return list.toArray(new int[list.size()][]);
}
}
#LeetCode 738. Monotone Increasing Digits
#LeetCode 738. 视频讲解:贪心算法,思路不难想,但代码不好写!LeetCode:738.单调自增的数字_哔哩哔哩_bilibili
首先把整数改为字符串的原因是方便逐位操作每一位数字,再将字符串转换为字符数组后,可以通过下标操作字符数组中的每一个字符,这样可以方便地修改每一位数字。最后,将修改后的字符数组重新转换为字符串,再将字符串转换为整数,得到最终结果。
设置一个flag 参数的作用是,记录在哪一位之后都变为9,如果不记录,在数字是1000 时,会因为后两位相同而不做任何操作,最后得到的数字是900而不是999。flag 的起始设置是指向数字的最后一位,是为了在没有需要更新操作的时候,可以不进行赋值为9 的操作。
整个的遍历顺序是从后向前操作,如果从前向后操作,对于数字332,那么会改为329,那么就不符合题目对于单调递增数列的要求了。
代码:
class Solution {
public int monotoneIncreasingDigits(int n) {
String s = String.valueOf(n);
char[] c = s.toCharArray();
int flag = c.length;
for (int i = c.length - 1; i > 0; i--) {
if (c[i] < c[i-1]) {
c[i-1]--;
flag = i;
}
}
for (int i = flag; i < c.length; i++) {
c[i] = '9';
}
return Integer.parseInt(String.valueOf(c));
}
}
#LeetCode 968. Binary Tree Cameras
#LeetCode 968. 视频讲解:贪心算法,二叉树与贪心的结合,有点难...... LeetCode:968.监督二叉树_哔哩哔哩_bilibili
遍历的顺序是后序遍历(左右中),因为要摄像的数目最少,从叶子节点考虑,进可能少的设置摄像。叶子节点的父节点是要放置摄像的,这样再相隔2 个节点再设置一个摄像。
每个节点的状态共有三种:
状态0: 无覆盖
状态1: 有摄像
状态2: 有覆盖
在这里考虑是否存在一个状态是:无摄像状态?其实无摄像状态就是0 或者2 的情况,所以不需要单独考虑。那么对于null 的节点,状态应该为2 ,这样可以叶子节点的父节点满足最少设置的要求。
需要考虑的情况共有4 种:
情况1: 左右节点都是有覆盖的情况,那么这个节点则设置为状态0,是无覆盖。
情况2: 左右节点中至少有一个无覆盖的情况,那这个节点需要设置为状态1,将会放置一个摄像。
情况3: 左右节点至少有一个摄像,那么这个节点属于状态2,因为左右孩子节点如果有摄像,其父节点也会被覆盖到。如果是一个节点有摄像,一个节点是无覆盖,那么则属于情况2,会将这个节点放置一个摄像。
情况4: 容易忘记的一个情况,是根节点无覆盖,那么需要单独考虑为这个节点放置一个摄像。
代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
int result = 0;
public int minCameraCover(TreeNode root) {
if (traversal(root) == 0) {
result ++; // case 4
}
return result;
}
public int traversal(TreeNode cur) {
if (cur == null) {
return 2;
}
int left = traversal(cur.left);
int right = traversal(cur.right);
if (left == 2 && right == 2) {
return 0; // case 1
} else if (left == 0 || right == 0) {
result ++;
return 1; // case 2
} else {
return 2; // case 3
}
}
}