力扣解法汇总825-适龄的朋友

原题链接:力扣


描述:

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

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

ages[y] <= 0.5 * ages[x] + 7
ages[y] > ages[x]
ages[y] > 100 && ages[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 * 104
1 <= ages[i] <= 120

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

解题思路:

* 我们转化为满足三个条件的所有组合,则需要同时满足下面三个条件:
* 1。ages[x]>=ages[y]
* 2。ages[y]>0.5*ages[x]+7
* 3。ages[x]>=100||y<=100
* 首先第一个,条件,我们对数组从大到小排序,先取X后取Y。然后加上另外两个判断条件,则就可以依次统计了。
* 基本的解法出来后,我们就得考虑如何优化了,因为现在的时间复杂度是O(n2)
* 优化点就是第二个for循环我们其实都是在找一个临界值,只要找到这个临界值,比如67,那么大于67的都是符合的,就不用一个一个的去判断了。

代码:

 /**
     * 解法2,优化后二分查找的方案
     *
     * @param ages
     * @return
     */
    public int numFriendRequests2(int[] ages) {
        ages = Arrays.stream(ages).boxed().sorted((a, b) -> b - a).mapToInt(p -> p).toArray();
        int xIndex = 0;
        int x;
        int num = 0;
        int yCompare = 0;
        int xStart = 0;
        Boolean isMoreThan100 = null;
        for (int i = 0; i < ages.length; i++) {
            xIndex = i;
            x = ages[xIndex];
            yCompare = x / 2 + 7;
            if (isMoreThan100 == null || isMoreThan100) {
                isMoreThan100 = x >= 100;
            }
            if (ages[xStart] != x) {
                xStart = i;
            }

            //这里拆分成两个条件进行判断,二分查找找临界值
            if (isMoreThan100) {
                //找大于yCompare的数量
                int targetIndex = binarySearchForIndexByReverse(ages, yCompare, xStart, ages.length - 1, true);
                while (ages[targetIndex] == yCompare) {
                    targetIndex--;
                }
                num += (targetIndex - xStart);
                continue;
            }
            if (yCompare > 100) {
                continue;
            }
            //这里的判断y<=100,基本上不需要判断,因为yCompare一定是在100的右边
            int targetIndex1 = binarySearchForIndexByReverse(ages, yCompare, xStart, ages.length - 1, true);
            while (ages[targetIndex1] == yCompare) {
                targetIndex1--;
            }
            int i1 = targetIndex1 - xStart;
            if (i1 > 0) {
                num += i1;
            }
        }
        return num;
    }

    public static int binarySearchForIndexByReverse(int[] array, int target, int start, int end, boolean vague) {
        if (target > array[0]) {
            if (vague) {
                return 0;
            }
            return -1;
        }
        if (target < array[array.length - 1]) {
            if (vague) {
                return array.length - 1;
            }
            return -1;
        }

        int middle = 0;
        while (true) {
            middle = (start + end) / 2;
            if (target == array[middle]) {
                break;
            }
            if (start == end) {
                //找不到时的处理逻辑
                if (vague) {
                    return start;
                }
                return -1;
            }
            if ((end - start) == 1) {
//                直接判断
                if (array[start] == target) {
                    return start;
                } else if (array[end] == target) {
                    return end;
                } else {
                    if (vague) {
                        return start;
                    }
                    return -1;
                }
            }
            if (array[middle] < target) {
                end = middle;
            } else {
                start = middle;
            }
        }
        return middle;
    }

    /**
     * 解法1,最初方案,双重for循环
     */
    public int numFriendRequests(int[] ages) {
        ages = Arrays.stream(ages).boxed().sorted((a, b) -> b - a).mapToInt(p -> p).toArray();
        int xIndex = 0;
        int yIndex = 0;
        int x;
        int y;
        int num = 0;
        int yCompare = 0;
        int xStart = 0;
        Boolean isMoreThan100 = null;
        for (int i = 0; i < ages.length; i++) {
            xIndex = i;
            x = ages[xIndex];
            yCompare = x / 2 + 7;
            if (isMoreThan100 == null || isMoreThan100) {
                isMoreThan100 = x >= 100;
            }
            if (ages[xStart] != x) {
                xStart = i;
            }
            for (yIndex = xStart; yIndex < ages.length; yIndex++) {
                if (xIndex == yIndex) {
                    continue;
                }
                y = ages[yIndex];
                //这里可以根据具体的条件,进行二分法查找临界点
                if (y > yCompare && (isMoreThan100 || y <= 100)) {
                    num++;
                }
            }
        }
        return num;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失落夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值