文章目录
- 933. Number of Recent Calls
- 883. Projection Area of 3D Shapes
- 589. N-ary Tree Preorder Traversal
- 590. N-ary Tree Postorder Traversal
- 700. Search in a Binary Search Tree
- 908. Smallest Range I
- 867. Transpose Matrix
- 876. Middle of the Linked List
- 559. Maximum Depth of N-ary Tree
- 557. Reverse Words in a String III
- 811. Subdomain Visit Count
- 344. Reverse String
- 806. Number of Lines To Write String
- 476. Number Complement
933. Number of Recent Calls
求最近的ping请求次数(3000毫秒内)
Input: inputs = [“RecentCounter”,“ping”,“ping”,“ping”,“ping”], inputs = [[],[1],[100],[3001],[3002]]
Output: [null,1,2,3,3]
因为时间是递增的,而题目要求输出最近3000ms内的ping数,只需要把所有ping加到队列中,然后把过期的删掉,剩下的就是符合条件的。
public class RecentCounter{
Queue<Integer> q = new LinkedList<>();
public int ping(int t){
q.offer(t);
while(t - q.peek() > 3000){//从头开始遍历把超过3000的删掉
q.poll();
}
return q.size();
}
}
883. Projection Area of 3D Shapes
计算三视图投影面积之和
其中 v = grid[i][j],(i, j)表示立方体所在单元格,v表示立方体高度
Input: [[2]]
Output: 5
Explanation:[0,0]这个格子,有个高度为2的立方体,左视图2,正视图为2,俯视图为1,所以面试之和为5
Input: [[1,2],[3,4]]
Output: 17
Explanation:
Here are the three projections (“shadows”) of the shape made with each axis-aligned plane.
[
[1, 2],
[3, 4]
]
解释:
(0,0)有个高度为1的立方体,
(0,1)为2的立方体,
(1,0)位置有高度为3的立方体,
(1,1)位置有个高度为4的立方体
从上面看(x-y平面 ,俯视)有四个高度不为0的立方体,所以俯视图面积为4
从正面看(x-z平面)前面有高度1,3
两个立方体,后面有2,4
两个立方体。2>1,4>3
所以正试图看到的是后面的投影面积,也就是·2+4=6
从侧面看(y-z平面)前面有高度1,2
两个立方体,后面有3,4
两个立方体,3>1,4>2
,所以投影面积为较大者的投影之和,即3+4=7
所以总面积为4+6+7=17
从上面可看出,正视图求的是数组列最大值之和,侧视图求的是数组行最大值之和,俯视图是非0高度元素之和。
public int projectionArea(int[][] grid) {
int t = 0;
int f = 0;
int s = 0;
for(int row = 0, rowMax = 0, colMax = 0; row < grid.length; row++){
for(int col = 0; col < grid[row].length; col++){
if(rowMax < grid[row][col]){//求出每一行的最大值
rowMax = grid[row][col];
}
if(colMax < grid[col][row]){//每一列的最大值
colMax = grid[col][row];
}
if (grid[row][col] > 0) t++;//非0立方体数量
}
f += rowMax;//求行/列最大值之和
s += colMax;
//每一行和列扫描后,清0;
rowMax = 0;
colMax = 0;
}
return t + s + f;
}
589. N-ary Tree Preorder Traversal
590. N-ary Tree Postorder Traversal
树的先/后序遍历
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val,List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
List<Integer> list = new ArrayList<>();
//先序
public List<Integer> preorder(Node root) {
pre(root);
return list;
}
void pre(Node node){
if(node != null){
list.add(node.val);//先遍历自己
if(node.children != null){
for(Node n: node.children){//后递归遍历子节点
pre(n);
}
}
}
}
//后续
public List<Integer> postorder(Node root) {
post(root);
return list;
}
void post(Node node){
if(node != null){
if(node.children != null){
for(Node n: node.children){
post(n);
}
}
list.add(node.val);
}
}
}
700. Search in a Binary Search Tree
二叉搜索树中搜索一个元素,返回整个子树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
//如果当前为空或者值相等 返回当前节点。
if(root == null || root.val == val) return root;
if(val < root.val)//如果待搜值小于当前节点,递归在左子树搜索
return searchBST(root.left, val);
else
return searchBST(root.right, val);
}
}
908. Smallest Range I
这题题目难懂,
给一个数组A,再给一个数K,数组中的每一个数都可以’加上(+)’ [-k,k]这个区间的一个数,得到其他新数组。求得到的新数组中,最大值与最小值的差值的最小值。
常规思路:
第一步: 计算出所有可能数组
第二步: 计算出每个数组的最大值与最小值的差值
第三部: 第二步得到的每个数组的差值可组成一个新的数组,求这个数组的最小值
复杂度为O( n 2 k n^{2k} n2k)(每个数都有2k种加减可能,n个数就会有 n 2 k n^{2k} n2k种情形)—放弃—
思路2:
上一种是先算出所有可能数组再去求差,这样可能数组太多,不好求
这次先求出最大最小值的差,再去加(-k,k)区间的数让这个差变小
如A = [1, 3, 6], K = 3
max = 6 , min = 1
max - min = 5
要让差值尽可能小,那就要max尽量小,min尽量大
那max = max -k
能最小,min = min +k
能最大;
所以max-k - (min + k) = max - min - 2*k
,为最小值
而题目要求最大减最小,所以结果一定非负。
如果max-k < min+k
,说明max-(-k,k),min+(-k,k)的过程会有相遇,存在差值为0
的情况
public int smallestRangeI(int[] A, int K) {
int min = A[0], max = A[0];
for(int a: A){//遍历找到最大最小值
if(a < min){
min = a;
}else if(a > max){
max = a;
}
}
return (max - k < min +k) ? 0 : (max - min - 2 * k);
}
867. Transpose Matrix
矩阵转置。根据主对角线,翻转矩阵
public int[][] transpose(int[][] A) {
int[][] R = new int[A[0].length][A.length];//新建一个行列数相反的空矩阵
for(int i = 0; i < A.length; i++){
for(int j = 0; j< A[i].length; j++){
R[j][i] = A[i][j];
}
}
return R;
}
876. Middle of the Linked List
求一个链表的中间节点
这里用两个指针,慢指针走一步,快指针走两步,当快指针走到终点时,慢指针刚好到中点。
public ListNode middleNode(ListNode head) {
ListNode sNode = head, qNode = head;
while(qNode!=null && qNode.next != null){
sNode = sNode.next;
qNode = qNode.next.next;
}
return sNode;
}
559. Maximum Depth of N-ary Tree
求树的最大深度
public int maxDepth(Node root) {
if(root == null) return 0;
if(root.children == null) return 1;
int max = 0;
//递归求出每个子树的最大高度,取其中最大那个
for(Node node: root.children){
int d = maxDepth(node);
if(d > max) max = d;
}
return max + 1;
}
557. Reverse Words in a String III
字符串以空格分开,倒序每一个字串
Input: “Let’s take LeetCode contest”
Output: “s’teL ekat edoCteeL tsetnoc”
先按照空格切分为字符串数组,然后对每一个字符串倒序,最后再以空格连接起来。
public String reverseWords(String s) {
String[] ss = s.split(" ");
StringBuilder sb = new StringBuilder();
for(int i = 0; i < ss.length; i++){
sb.append(new StringBuilder().append(ss[i]).reverse());
if(i < ss.length - 1){
sb.append(" ");
}
}
return sb.toString();
}
811. Subdomain Visit Count
求所有子域名访问次数
Example 2:
Input:
[“900 google.mail.com”, “50 yahoo.com”, “1 intel.mail.com”, “5 wiki.org”]
Output:
[“901 mail.com”,“50 yahoo.com”,“900 google.mail.com”,“5 wiki.org”,“5 org”,“1 intel.mail.com”,“951 com”]
Explanation:
We will visit “google.mail.com” 900 times, “yahoo.com” 50 times, “intel.mail.com” once and “wiki.org” 5 times. For the subdomains, we will visit “mail.com” 900 + 1 = 901 times, “com” 900 + 50 + 1 = 951 times, and “org” 5 times.
public List<String> subdomainVisits(String[] cpdomains) {
List<String> list = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
for (String domain : cpdomains) {
String[] ds = domain.split(" ");//空格切分为访问次数和访问域名
String[] split = ds[1].split("\\.");//点分隔开,后面的循环再从根域名开始拼接为子域名
int n = Integer.parseInt(ds[0]);//访问次数
String s = "";
for (int i = split.length - 1; i >= 0; i--) {
s = split[i] + s;
map.put(s, map.getOrDefault(s, 0) + n);//如果map种没有就设为n,有就取出来再加上n
s = "." + s;
}
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
list.add(entry.getValue() + " " + entry.getKey());
}//遍历map
return list;
}
344. Reverse String
字符串翻转
Input: “hello”
Output: “olleh”
//直接调用StringBuilder的reverse方法
public String reverseString(String s) {
StringBuilder sb = new StringBuilder();
return sb.append(s).reverse().toString();
}
//首尾交换进行翻转
public String reverseString(String s) {
if(s == null || s.length() == 0) return s;
char[] cs = s.toCharArray();
int i = 0, j = cs.length - 1;
while(i < j){
char t = cs[i];
cs[i++] = cs[j];
cs[j--] = t;
}
return new String(cs);
}
806. Number of Lines To Write String
给一个长度为26的数组表示a-z每个字母的宽度,给一个字符串S
每行最多只能容下100宽度的字符
求需要几行,最后一行占多少宽度。
Example :
Input:
widths = [10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10]
S = “abcdefghijklmnopqrstuvwxyz”
Output: [3, 60]
Explanation:
All letters have the same length of 10. To write all 26 letters,
we need two full lines and one line with 60 units.
3行才能容下26个字母,最后一行有6个字母占宽6*10
public int[]numberOfLines(int[] widths, String S) {
char[] cs = S.toCharArray();
int line = 1, left = 0;
for(char c: cs){
int w = widths[c-'a'];//c字符占的宽度
//加上当前字符的宽度后,判断是否大于100
if(left + w > 100){//是的话,行数+1,最后一行的宽度初始化为w
line++;
left = w;
}else{//否则继续增加
left += w;
}
}
return new int[]{line, left};
}
476. Number Complement
求一个数字的补充数(反码)
public int findComplement(int num) {
int a = 1;
//计算出比num高的最小2的倍数
//这方法leetcode运行超时,也不知道为什么
while(a <= num){//比如num = 5(0b101),a = 8(0b1000)
a <<= 1;
}
//下面这个就没超时
//int c = num;
//while(c != 0){
// c >>= 1;
// a <<= 1;
//}
return a - 1 - num;//a - 1 = 0b111
}