LeetCode 1609. 奇偶树 / 1078. Bigram 分词 / 825. 适龄的朋友(计数排序)

Posted Zephyr丶J

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 1609. 奇偶树 / 1078. Bigram 分词 / 825. 适龄的朋友(计数排序)相关的知识,希望对你有一定的参考价值。

1609. 奇偶树

2021.12.25 每日一题,圣诞快乐,考研顺利,今天没有圣诞树,但是有奇偶树

题目描述

如果一棵二叉树满足下述几个条件,则可以称为 奇偶树 :

二叉树根节点所在层下标为 0 ,根的子节点所在层下标为 1 ,根的孙节点所在层下标为 2 ,依此类推。
偶数下标 层上的所有节点的值都是 奇 整数,从左到右按顺序 严格递增
奇数下标 层上的所有节点的值都是 偶 整数,从左到右按顺序 严格递减
给你二叉树的根节点,如果二叉树为 奇偶树 ,则返回 true ,否则返回 false 。

示例 1:


输入:root = [1,10,4,3,null,7,9,12,8,6,null,null,2]
输出:true
解释:每一层的节点值分别是:
0 层:[1]
1 层:[10,4]
2 层:[3,7,9]
3 层:[12,8,6,2]
由于 0 层和 2 层上的节点值都是奇数且严格递增,而 1 层和 3 层上的节点值都是偶数且严格递减,因此这是一棵奇偶树。

示例 2:


输入:root = [5,4,2,3,3,7]
输出:false
解释:每一层的节点值分别是:
0 层:[5]
1 层:[4,2]
2 层:[3,3,7]
2 层上的节点值不满足严格递增的条件,所以这不是一棵奇偶树。

示例 3:


输入:root = [5,9,1,3,5,7]
输出:false
解释:1 层上的节点值应为偶数。

示例 4:

输入:root = [1]
输出:true

示例 5:

输入:root = [11,8,6,1,3,9,11,30,20,18,16,12,10,4,2,17]
输出:true

提示:

树中节点数在范围 [1, 10^5] 内
1 <= Node.val <= 10^6

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/even-odd-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

层序遍历就行了

/**
 * Definition for a binary tree node.
 * public class TreeNode 
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() 
 *     TreeNode(int val)  this.val = val; 
 *     TreeNode(int val, TreeNode left, TreeNode right) 
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     
 * 
 */
class Solution 
    public boolean isEvenOddTree(TreeNode root) 
        //就是一个简单的层序遍历吧,想想
        //层序遍历,因为每一层都是从左到右记录的,所以直接看是否递增递减和奇偶性就可以了
        
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int level = 0;
        while(!queue.isEmpty())
            int size = queue.size();
            int last = -1;
            while(size-- > 0)
                TreeNode node = queue.poll();
                int val = node.val;
                //如果是奇数层
                if((level & 1) == 1)
                    if((val & 1) == 1)
                        return false;
                    if(last != -1 && val >= last)
                        return false;
                else
                    if((val & 1) == 0)
                        return false;
                    if(last != -1 && val <= last)
                        return false;
                
                if(node.left != null)
                    queue.offer(node.left);
                if(node.right != null)
                    queue.offer(node.right);
                    
                last = node.val;
            
            level++;
        
        return true;
    

1078. Bigram 分词

2021.12.26 每日一题

题目描述

给出第一个词 first 和第二个词 second,考虑在某些文本 text 中可能以 “first second third” 形式出现的情况,其中 second 紧随 first 出现,third 紧随 second 出现。

对于每种这样的情况,将第三个词 “third” 添加到答案中,并返回答案。

示例 1:

输入:text = “alice is a good girl she is a good student”, first = “a”, second = “good”
输出:[“girl”,“student”]

示例 2:

输入:text = “we will we will rock you”, first = “we”, second = “will”
输出:[“we”,“rock”]

提示:

1 <= text.length <= 1000
text 由小写英文字母和空格组成
text 中的所有单词之间都由 单个空格字符 分隔
1 <= first.length, second.length <= 10
first 和 second 由小写英文字母组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/occurrences-after-bigram
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

注意toArray()的用法

class Solution 
    public String[] findOcurrences(String text, String first, String second) 
        String[] txt = text.split(" ");
        List<String> list = new ArrayList<>();
        for(int i = 2; i < txt.length; i++)
            if(txt[i - 2].equals(first) && txt[i - 1].equals(second))
                list.add(txt[i]);
        
        return list.toArray(new String[]);
    

825. 适龄的朋友

2021.12.27 每日一题

题目描述

在社交媒体网站上有 n 个用户。给你一个整数数组 ages ,其中 ages[i] 是第 i 个用户的年龄。

如果下述任意一个条件为真,那么用户 x 将不会向用户 y(x != y)发送好友请求:

age[y] <= 0.5 * age[x] + 7
age[y] > age[x]
age[y] > 100 && age[x] < 100
否则,x 将会向 y 发送一条好友请求。

注意,如果 x 向 y 发送一条好友请求,y 不必也向 x 发送一条好友请求。另外,用户不会向自己发送好友请求。

返回在该社交媒体网站上产生的好友请求总数。

示例 1:

输入:ages = [16,16]
输出:2
解释:2 人互发好友请求。

示例 2:

输入:ages = [16,17,18]
输出:2
解释:产生的好友请求为 17 -> 16 ,18 -> 17 。

示例 3:

输入:ages = [20,30,100,110,120]
输出:3
解释:产生的好友请求为 110 -> 100 ,120 -> 110 ,120 -> 100 。

提示:

n == ages.length
1 <= n <= 2 * 10^4
1 <= ages[i] <= 120

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/friends-of-appropriate-ages
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

第一时间被第三个条件给迷惑了,导致问题出了一大堆
发现问题后,又自然而然的认为两个相同的值是肯定要交流的,所以一直没发现错误
最终debug终于发现了问题,好不容易过了
其实应该写个双指针的
双指针更简单

class Solution 
    
    public int numFriendRequests(int[] ages) 
        //首先看条件,发现100以上和100以下是不会进行交流的,所以可以把年龄段分为100以上和100以下两个部分,且都包含100
        //0.5 * age[x] + 7 < age[y] <= age[x]
        //年龄大的给年龄小的发请求,小的不会给大的发
        //想到一个思路,先排序,然后对于每一个年龄,查找可以发送请求的范围,找到这个值以后,通过下标来计算个数

        //错了,第三个条件只是说小于100的不给大于100的发消息,但是大于100的可以给小于100的发
        //然后再看第三个条件,x小于100,y大于100,第二个条件就给出不成立了,所以相当于恒成立............
        //搞的我处理了半天这个条件

        int n = ages.length;
        Arrays.sort(ages);
        int res = 0;
        for(int i = 0; i < n;)
            int left = 0;
            int right = i - 1;
            double range = 0.5 * ages[i] + 7;
            
            while(left < right)
                int mid = (right - left + 1) / 2 + left;
                //如果满足条件的,那么就再往左边找第一个满足条件的
                if((double)ages[mid] > range)
                    right = mid - 1;
                else
                    left = mid;
                
            

            //找相同值
            int t = i + 1;
            while(t < n && ages[t] == ages[i])
                t++;
            

            //如果left位置处的值满足条件
            if((double)ages[left] > range)
                int add = t - 1 - left;
                res += (t - i) * add;

            //如果不满足条件,那么只计算相同的
            else
                int add = t - left - 2;
                if(add > 0 && (double)ages[i] > range)
                    res += (t - i) * add;
            
            i = t;
        
        return res;
    

双指针,但是竟然比二分要慢

class Solution 
    public int numFriendRequests(int[] ages) 
        //双指针果然更简单
        
        int n = ages.length;
        Arrays.sort(ages);
        int left = 0, right = 0, ans = 0;
        for (int age : ages) 
            if (age < 15) 
                continue;
            
            while (ages[left] <= 0.5 * age + 7) 
                ++left;
            
            while (right + 1 < n && ages[right + 1] <= age) 
                ++right;
            
            ans += right - left;
        
        return ans;
    


计数排序,统计每个年龄的人数,然后对于每一个年龄,计算满足条件的人的个数
用前缀和优化这个过程

class Solution 
    public int numFriendRequests(int[] ages) 
        //计数排序
        //统计每个年龄的人数,然后对于每一个年龄,计算符合要求的人数
        int[] num = new int[121];
        for(int age : ages)
            num[age]++;
        
        int[] pre = new int[121];
        for(int i = 1; i < 121; i++)
            pre[i] = pre[i - 1] + num[i];
        
        int ans = 0;
        for(int i = 15; i < 121; i++)
            int range = (int)(0.5 * i) + 7;
            if(num[i] > 0)
                ans += num[i] * (pre[i] - pre[range] - 1);
            
        
        return ans;
    


以上是关于LeetCode 1609. 奇偶树 / 1078. Bigram 分词 / 825. 适龄的朋友(计数排序)的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 1609. 奇偶树

LeetCode 1609 奇偶数[BFS] HERODING的LeetCode之路

1078 最小生成树

1078 最小生成树

LeetCode -- 1078. Occurrences After Bigram

hihoCoder #1078 : 线段树的区间修改(线段树区间更新板子题)