【LeetCode】Day 3
文章目錄
- 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( )(每個數都有2k種加減可能,n個數就會有 種情形)—放棄—
思路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
}