【LeetCode】Day 3

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.
a
[
[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
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值