给你一个仅由数字 6 和 9 组成的正整数 num。
你最多只能翻转一位数字,将 6 变成 9,或者把 9 变成 6 。
请返回你可以得到的最大数字。
示例 1:
输入:num = 9669
输出:9969
解释:
改变第一位数字可以得到 6669 。
改变第二位数字可以得到 9969 。
改变第三位数字可以得到 9699 。
改变第四位数字可以得到 9666 。
其中最大的数字是 9969 。
示例 2:
输入:num = 9996
输出:9999
解释:将最后一位从 6 变到 9,其结果 9999 是最大的数。
示例 3:
输入:num = 9999
输出:9999
解释:无需改变就已经是最大的数字了。
class Solution {
public int maximum69Number (int num) {
String snum = String.valueOf(num);
int slen = snum.length(), i = 0;
for (i=0; i <slen; ++i) {
if (snum.charAt(i) == '6') {
return Integer.parseInt(snum.substring(0, i) + '9' + snum.substring(i+1));
}
}
return num;
}
};
给你一个字符串 s。请你按照单词在 s 中的出现顺序将它们全部竖直返回。
单词应该以字符串列表的形式返回,必要时用空格补位,但输出尾部的空格需要删除(不允许尾随空格)。
每个单词只能放在一列上,每一列中也只能有一个单词。
示例 1:
输入:s = “HOW ARE YOU”
输出:[“HAY”,“ORO”,“WEU”]
解释:每个单词都应该竖直打印。
“HAY”
“ORO”
“WEU”
示例 2:
输入:s = “TO BE OR NOT TO BE”
输出:[“TBONTB”,“OEROOE”," T"]
解释:题目允许使用空格补位,但不允许输出末尾出现空格。
“TBONTB”
“OEROOE”
" T"
示例 3:
输入:s = “CONTEST IS COMING”
输出:[“CIC”,“OSO”,“N M”,“T I”,“E N”,“S G”,“T”]
提示:
1 <= s.length <= 200
s 仅含大写英文字母。
题目数据保证两个单词之间只有一个空格。
class Solution {
public List<String> printVertically(String s) {
s = s.trim();
ArrayList<String> ans = new ArrayList<>();
String[] words = s.split(" ");
int n = words.length, i = 0, lmax = 0, j = 0;
for (String word: words) {
lmax = Math.max(lmax, word.length());
}
char[] chs = new char[n];
for (j=0; j<lmax; ++j) {
Arrays.fill(chs, '0');
for (i=0; i<n; ++i) {
if (j < words[i].length()) {
chs[i] = words[i].charAt(j);
} else {
chs[i] = ' ';
}
}
String tmp = new String(chs);
tmp = 'a' + tmp;
tmp = tmp.trim();
tmp = tmp.substring(1);
ans.add(tmp);
}
return ans;
}
}
给你一棵以 root 为根的二叉树和一个整数 target ,请你删除所有值为 target 的 叶子节点 。
注意,一旦删除值为 target 的叶子节点,它的父节点就可能变成叶子节点;如果新叶子节点的值恰好也是 target ,那么这个节点也应该被删除。
也就是说,你需要重复此过程直到不能继续删除。
示例 1:
输入:root = [1,2,3,2,null,2,4], target = 2
输出:[1,null,3,null,4]
解释:
上面左边的图中,绿色节点为叶子节点,且它们的值与 target 相同(同为 2 ),它们会被删除,得到中间的图。
有一个新的节点变成了叶子节点且它的值与 target 相同,所以将再次进行删除,从而得到最右边的图。
示例 2:
输入:root = [1,3,3,3,2], target = 3
输出:[1,3,null,null,2]
示例 3:
输入:root = [1,2,null,2,null,2], target = 2
输出:[1]
解释:每一步都删除一个绿色的叶子节点(值为 2)。
示例 4:
输入:root = [1,1,1], target = 1
输出:[]
示例 5:
输入:root = [1,2,3], target = 1
输出:[1,2,3]
提示:
1 <= target <= 1000
每一棵树最多有 3000 个节点。
每一个节点值的范围是 [1, 1000] 。
递归。先处理左右子树,返回左右子树根节点,根据更新的左右子节点判断当前根节点是否需要删除。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode removeLeafNodes(TreeNode root, int target) {
if (root == null) {
return null;
}
root.left = removeLeafNodes(root.left, target);
root.right = removeLeafNodes(root.right, target);
if (root.left == null && root.right == null) {
return root.val == target? null: root;
}
return root;
}
}
在 x 轴上有一个一维的花园。花园长度为 n,从点 0 开始,到点 n 结束。
花园里总共有 n + 1 个水龙头,分别位于 [0, 1, …, n] 。
给你一个整数 n 和一个长度为 n + 1 的整数数组 ranges ,其中 ranges[i] (下标从 0 开始)表示:如果打开点 i 处的水龙头,可以灌溉的区域为 [i - ranges[i], i + ranges[i]] 。
请你返回可以灌溉整个花园的 最少水龙头数目 。如果花园始终存在无法灌溉到的地方,请你返回 -1 。
示例 1:
输入:n = 5, ranges = [3,4,1,1,0,0]
输出:1
解释:
点 0 处的水龙头可以灌溉区间 [-3,3]
点 1 处的水龙头可以灌溉区间 [-3,5]
点 2 处的水龙头可以灌溉区间 [1,3]
点 3 处的水龙头可以灌溉区间 [2,4]
点 4 处的水龙头可以灌溉区间 [4,4]
点 5 处的水龙头可以灌溉区间 [5,5]
只需要打开点 1 处的水龙头即可灌溉整个花园 [0,5] 。
示例 2:
输入:n = 3, ranges = [0,0,0,0]
输出:-1
解释:即使打开所有水龙头,你也无法灌溉整个花园。
示例 3:
输入:n = 7, ranges = [1,2,1,0,2,1,0,1]
输出:3
示例 4:
输入:n = 8, ranges = [4,0,0,0,0,0,0,0,4]
输出:2
示例 5:
输入:n = 8, ranges = [4,0,0,0,4,0,0,0,4]
输出:1
提示:
1 <= n <= 10^4
ranges.length == n + 1
0 <= ranges[i] <= 100
区间覆盖问题。将线段按照左端点从小到大排序,维护两个变量curLen
和curIdx
,分别表示当前所选区间集合最右端覆盖的位置和当前所选的线段的Id. 每次从curIdx
开始,在有序的线段数组中二分查找最后一个左端点位于curLen
左侧的线段tmpIdx
,在(curIdx, tmpIdx]
区间中寻找右端点最右的线段的Id作为新的curIdx
, 该线段的右端点位置作为新的curLen
. 如此循环直到区间完全覆盖,记录所用的线段个数返回。
注意rightmostNoLargerThan
的二分查找的写法,主要关注while
循环条件l <= r
和返回值return r
.
class Solution {
private class Line implements Comparable<Line> {
public int left, right;
public Line(int left, int right) {
this.left = left;
this.right = right;
}
@Override
public int compareTo(Line other) {
return left - other.left;
}
}
private int rightmostNoLargerThan(Line[] lines, int beginIdx, int bound) {
int n = lines.length, l = Math.max(beginIdx, 0), r = n-1, m = 0;
while (l <= r) {
m = (l + r) / 2;
if (lines[m].left <= bound) {
l = m + 1;
} else {
r = m - 1;
}
}
return r;
}
public int minTaps(int n, int[] ranges) {
Line[] lines = new Line[n+1];
int i = 0;
for (i=0; i<=n; ++i) {
lines[i] = new Line(i - ranges[i], i + ranges[i]);
}
Arrays.sort(lines);
int curLen = 0, curIdx = -1, cnt = 0, preLen = 0;
while (curLen < n) {
int tmpIdx = rightmostNoLargerThan(lines, curIdx, curLen);
preLen = curLen;
for (i=curIdx + 1; i<=tmpIdx; ++i) {
if (lines[i].right > curLen) {
curLen = lines[i].right;
curIdx = tmpIdx;
}
}
if (preLen == curLen) {
return -1;
}
++cnt;
}
return cnt;
}
}