2021-07-01 Leetcode题解:545,915,1647,722

545. Boundary of Binary Tree
题目:Recursion

  • 给定一个树形结构,返回 [ 根节点,左边界(为一个list),从左到右的所有叶子结点,及反序右边界] 的concatenation
  • 左边界中的节点包括:
    1. 根节点的左儿子。若根节点无左儿子,左边界中无节点
    1. 左边界中节点的左儿子,或无左儿子的节点的右儿子
    1. 须删掉最左的叶节点。* 由于左边界为沿着一棵树的最左走到底,遇到的第一个也是唯一一个叶节点即为最左的叶节点
  • 右边界定义同理
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):        
    def boundaryOfBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        def findLeaves(node):
            if (not node.left and not node.right):
                if (node!=root):
                    res.append(node.val)
                return
            if (node.left):
                findLeaves(node.left)
            if (node.right):
                findLeaves(node.right)
                
        def findLeftB(res, node):
            if (node==root and not root.left):
                return
            
            if (node!=root):
                res.append(node.val)
            if (not node.left and not node.right):
                res.pop() #remove leftmost leaf
                return
            
            if (node.left):
                findLeftB(res, node.left)
            elif (node.right):
                findLeftB(res, node.right)

        def findRightB(res, node):
            if (node==root and not root.right):
                return
            
            if (node!=root):
                res.append(node.val)
            if (not node.left and not node.right):
                res.pop()
                return
            
            if (node.right):
                findRightB(res, node.right)
            elif (node.left):
                findRightB(res, node.left)

        
        res = [root.val]
        findLeftB(res, root)
        findLeaves(root)
        idx = len(res)
        findRightB(res, root)
        a = res[idx:]
        a.reverse()
        res = res[0:idx]+a
        return res
        

915. Partition Array into Disjoint Intervals
题目大意:给定数组nums = [5,0,3,8,6],划分成两个subarray: left & right使得max{left} <= min{right}
思路: 顺序记录leftmax,倒序记录minright,从左到右找到第一个满足max{left} <= min{right}的划分点

class Solution {
    public int partitionDisjoint(int[] nums) {
        int N = nums.length;
        int[] maxL = new int[N];
        int[] minR = new int[N];
        
        maxL[0] = nums[0];
        for (int i=1; i<N; i++) {
            maxL[i] = Math.max(maxL[i-1], nums[i]);
            //System.out.println(maxL[i]);
        }
        
        minR[N-1] = nums[N-1];
        for (int i=N-2; i>=0; i--) {
            minR[i] = Math.min(minR[i+1], nums[i]);
            //System.out.println(minR[i]);

        }
        
        int idx = 0;
        while (idx<N && maxL[idx]>minR[idx+1]) {
            idx++;
        }
        
        return idx+1;
    }
}

1647. Minimum Deletions to Make Character Frequencies Unique
先数频次,对频次排序,hashset记录distinct frequency,若频次出现重复则尝试删除,* 忽略频次0的重复出现

class Solution {
    public int minDeletions(String s) {
        int[] count = new int[26];
        char[] chars = s.toCharArray();
        for (char c : chars) {
            count[c-'a']++;
        }
        Arrays.sort(count);
        int idx = 0;
        while (count[idx]==0) idx++;
        
        int ans = 0;
        HashSet<Integer> freq =new HashSet<Integer>();
        while (idx<26) {
            int t = count[idx];
            if (!freq.contains(t)) {
                freq.add(t);
            } else {
                while (t>0) {
                    if (!freq.contains(t)) break;
                    t--;
                }
                if (t!=0) freq.add(t);
                ans += count[idx] - t;
                //System.out.println(ans);
            }
            
            idx++;
        }
        
        return ans;
        
    }
}

722 Remove Comments

  • 题目描述
    • 从C++代码中删除注释,多行"/* … */",单行"//"。注意:
    1. “/* … */” 中的 “//” 不起作用 ,同理 同一行中"//" 后的 “/*” 不起作用
    1. 特殊情况!!"/*/" 作为多行注释的开始并不能结束多行注释,但作为多行注释的结尾可以结束多行注释(故只能在开始时跳过"/*/", 而不能在判断closing的时候处理该coner case)
    1. 空字符串不应被加入答案
    1. 删掉多行注释的开头行和结束行的内容应该被合并, 即[“a/.", "…/b”]需要被合并为[“ab”]而非 [“a”, “b”]
  • 最好使用while循环而非for循环来控制index,因为需要连续跳过注释的内容
class Solution {
    public List<String> removeComments(String[] source) {
        List<String> ans = new ArrayList<>();
        
        int flag1 = 0, flag2=0; // flag1 for /*, flag2 for //, 1 = exist
        StringBuilder sb = new StringBuilder();

        for (String s : source) {
            char[] chars = s.toCharArray();
            int N = chars.length;
            
            int i=0;
            while (i<N) {
                if (flag1 == 1) { // in /*
                    if (chars[i]=='*' && i+1<N && chars[i+1]=='/') {
                        flag1 = 0;
                        i+=2;
                        continue;
                    }
                } else {//not in /*
                    if (chars[i]=='/') { 
                        if (i+1<N && chars[i+1]=='*') { //start an /*
                            flag1 = 1;
                            i+=2;
                            if (i<N && chars[i]=='/') i++; //corner case /*/
                            continue;
                        }
                        if (i+1<N && chars[i+1]=='/') { //start an // : jump to the end of the line
                            i=N;
                            continue;
                        }
                        
                    }
                }

                if (flag1==0) {
                    sb.append(chars[i]);
                }
                i++;
                
            }
            
            String str = sb.toString();
            if (!str.equals("") && flag1==0) {
                ans.add(str);		//only add and refresh when block comment is closed
                sb = new StringBuilder();
            }
                      
            //System.out.println(str);  
        }
        
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值