LeetCode Biweekly Contest 4 & Week Contest 145

1118. Number of Days in a Month
有一個比較容易記憶的算法:先判斷是不是世紀年(能否被100整除),如果是,則用前兩位去整除4,如果有餘數就是平年,如果餘數爲0則爲閏年。對於不是世紀年的年份,用後兩位去整除4,如果餘數不爲0,則爲平年,餘數爲0則爲閏年。

class Solution {
    public int numberOfDays(int Y, int M) {
        int[][] days={{31,28,31,30,31,30,31,31,30,31,30,31},{31,29,31,30,31,30,31,31,30,31,30,31}};//平年28天,閏年29天
        
        if(Y%100==0)
        {
            int tmp=Y/100;
            if((tmp%4)==0)
            {
                System.out.println("haha");
                return days[1][M-1];
            }
            else
                return days[0][M-1];
        }
        else if((Y%100%4)==0)
        {
            System.out.println("xixi");
            return days[1][M-1];
        }
            
        else
            return days[0][M-1];
    }
}

1119. Remove Vowels from a String

class Solution {
    public String removeVowels(String S) {
        
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<S.length();i++){
            char c=S.charAt(i);
            if(c=='a' || c=='e'|| c=='i'||c=='o'||c=='u')
                continue;
            sb.append(c);
        }
        return sb.toString();
        
    }
}

1120. Maximum Average Subtree
在進行遞歸的“遞”時,需要記錄以當前節點爲根節點的子樹的節點數量,這裏使用一個HashMap來存儲。而計算當前節點的均值需要左右子樹的均值和子樹節點數量。難度不是很大。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public static HashMap<TreeNode,Integer> map;
    
    public static double ans;
    public static double maximumAverageSubtree(TreeNode root) {
        
        map=new HashMap<>();
        ans=0;
        recursive(root);
        return ans;
    }
    
    public static double recursive(TreeNode root){
        if(root.left==null && root.right==null){
            map.put(root,1);
            ans=Math.max(ans,(double)root.val);
            return (double) root.val;
        }
        double leftVal=0,rightVal=0;
        if(root.left!=null)
            leftVal=recursive(root.left);
        if(root.right!=null)
            rightVal=recursive(root.right);
        double sum=leftVal*Double.valueOf(map.getOrDefault(root.left,0))+rightVal*Double.valueOf(map.getOrDefault(root.right,0))+root.val;
        map.put(root,map.getOrDefault(root.left,0)+map.getOrDefault(root.right,0)+1);
        double avg=sum/map.get(root);
        ans=Math.max(ans,avg);
        return avg;
    }
    
}

1121. Divide Array Into Increasing Sequences

class Solution {
    public boolean canDivideIntoSubsequences(int[] nums, int K) {
     
        HashMap<Integer,Integer> count=new HashMap<>();
        for(int i:nums)
            count.put(i,count.getOrDefault(i,0)+1);
        int index=Integer.MAX_VALUE,c=0;
        for(int i:count.keySet()){
            if(count.get(i)>c){
                index=i;
                c=count.get(i);
            }
        }
        return K*c<=nums.length;
    }
}

1122. Relative Sort Array

class Solution {
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        int[] ans=new int[arr1.length];
        HashMap<Integer,Integer> co=new HashMap<>();
        
        for(int i=0;i<arr1.length;i++)
            co.put(arr1[i],co.getOrDefault(arr1[i],0)+1);
        int j=0;
        for(int i=0;i<arr2.length;i++){
            int times=co.get(arr2[i]);
            for(int n=0;n<times;n++)
            {
                ans[j++]=arr2[i];
            }
            co.remove(arr2[i]);
        }
        System.out.println(j);
        int n=j;
        for(Integer key:co.keySet()){
            int t=co.get(key);
            while(t>0)
            {
                ans[n++]=key;
                t--;
            }
        }
        Arrays.sort(ans,j,n);
        return ans;
    }
}

1123. Lowest Common Ancestor of Deepest Leaves
關鍵點:對於最深的葉子的最淺的公共祖先,當第一個出現的某個節點的左右子樹等高時,該節點就是最深的葉子的最淺的公共祖先。如果不等高,該公共祖先必然在較高的子樹上。
算法一:該算法每到一個新節點就需要重新計算高度,而沒有利用已有的左右子樹的高度,時間複雜度爲O(n^2)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode lcaDeepestLeaves(TreeNode node) {
        if(node==null || height(node.left)==height(node.right))
            return node;
        return lcaDeepestLeaves(height(node.left)>height(node.right)?node.left:node.right);
    }
    
    public static int height(TreeNode node){
        if(node==null)
            return 0;
        return Math.max(height(node.left),height(node.right))+1;
    } 
}

算法二:將已有的左右子樹的高度緩存下來,類似於1120. Maximum Average Subtree的思想,這樣時間複雜度會下降到O(n)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public static HashMap<TreeNode,Integer> map=new HashMap<>();
    
    public TreeNode lcaDeepestLeaves(TreeNode node) {
        
        
        if(node==null || height(node.left)==height(node.right))
            return node;
        
        
        return lcaDeepestLeaves(height(node.left)>height(node.right)?node.left:node.right);
    }
    
    public static int height(TreeNode node){
        
        if(node==null)
            return 0;
        if(map.containsKey(node))
            return map.get(node);
        map.put(node,Math.max(height(node.left),height(node.right))+1);
        return map.get(node);
    }
    
}

算法三:與算法二類似的思想,通過定義帶高度的節點類型將左右子節點的高度緩存下來

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    public class Node{
        TreeNode node;
        int height;
        
        public Node(TreeNode node,int height){
            this.node=node;
            this.height=height;
        }
        
        public Node(int height){
            this(null,height);
        }
    }
    
    public TreeNode lcaDeepestLeaves(TreeNode node) {
        
        return recursive(node).node;            
    }
    public Node recursive(TreeNode node){
        if(node==null)
            return new Node(0);
        Node left=recursive(node.left);
        Node right=recursive(node.right);
        int cur_height=Math.max(left.height,right.height)+1;
        if(left.height>right.height)
            return new Node(left.node,cur_height);
        else if(left.height<right.height)
            return new Node(right.node,cur_height);
        else
            return new Node(node,cur_height);
    }
}

1124. Longest Well-Performing Interval
分別計算勞累天數和不勞累天數的前綴和,再用暴力方法搜索。
算法一:前綴和+暴力

class Solution {
    public int longestWPI(int[] hours) {
        int n=hours.length;
        int[] record1=new int[n+1];
        int[] record2=new int[n+1];
        
        /*
        1 2 3 4 5 6 7
        1 2 2 2 2 2 3
        0 0 1 2 3 4 4
        */
        for(int i=1;i<=n;i++){
            if(hours[i-1]>8)
            {
                record1[i]=record1[i-1]+1;
                record2[i]=record2[i-1];
            }
            else
            {
                record2[i]=record2[i-1]+1;
                record1[i]=record1[i-1];
            }             
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j>0;j--){
                if(record1[i]-record1[j-1]>record2[i]-record2[j-1])
                    ans=Math.max(ans,i-j+1);
            }
        }
        return ans;
    }
}

算法二:

class Solution {
    public int longestWPI(int[] hours) {
        
        HashMap<Integer,Integer> map=new HashMap<>();
        int sum=0,ans=0;
        for(int i=0;i<hours.length;i++){
            
            sum=hours[i]>8?sum+1:sum-1;
            if(sum>0)
                ans=i+1;
            else
            {
                if(map.containsKey(sum-1))
                    ans=Math.max(ans,i-map.get(sum-1));
            }
            map.putIfAbsent(sum,i);
        }
        return ans;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章