小红书笔试8.28 第二题【排序+双指针】

其他题目都有大佬写过了,我只分享一下第二题的一种解法。

法术

时间限制:3000MS
内存限制:589824KB

题目描述:

小明是一名魔法师,他会n种法术,其中第种法术的威力为aj,他经常通过双手各自释放一种法术来提升威力,能得到的威力值为双手各自释放的法术的威力的乘积,但是他还不够强大,双手释放的两种法术必须是不同的,即不能双手释放同一种法术。这天他接到了一个任务,需要释放威力值至少为K才能完成,他想请你帮他算一算,在两只手都释放法术的情况下,共有多少方案能达到威力值K。每种方案可记作(u,v),uV,其威力值为ay*ay, (u, v)和(v, u)会被视为不同的方案。

输入描述

第一行两个正整数n和K,表示法术数量和威力值需求。
第二行为n个正整数a1,a2……an,其中a,表示第i个法术的威力为a。

输出描述

输出威力值至少为K的方案数。

样例输入

3 3
3 2 1

样例输出

4

提示

1 <= n <= 30000, 1 <= K <= 10^16, 1 <= ai <= 10^9

【排序+双指针】
左指针left从0向后走,右指针right从n-1向前走。
记mul = a[left] * a[right],
-若mul >= k,说明a[right]与[left...right]之间的所有数相乘都满足>=k。
-若mul < k,说明左指针太小了,需要右移。


import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        long k = scanner.nextLong();
        long[] a = new long[n];
        for (int i = 0; i < n; ++i) {
            a[i] = scanner.nextLong();
        }
        Arrays.sort(a);
        int left = 0, right = n - 1;
        long ans = 0;
        while (left < right) {
            long mul = a[left] * a[right];
            if (mul >= k) {
                ans += right - left;
                --right;
            } else {
                ++left;
            }
        }

        System.out.println(ans * 2);
    }
}
全部评论
m
点赞 回复 分享
发布于 2022-08-29 01:25 安徽
一模一样的写法,JS只过了80%。
点赞 回复 分享
发布于 2022-09-04 16:03 重庆
楼主 请问为什么 是 ans += right - left;呀? 找到 mul>=k以后直接计算 l,r之间有多少种大小为2的排列可以吗?
点赞 回复 分享
发布于 2022-09-18 07:27 美国

相关推荐

我也曾抱有希望:说的好直白
点赞 评论 收藏
分享
死在JAVA的王小美:哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈,我也是,让我免了一轮,但是硬气拒绝了
点赞 评论 收藏
分享
6 7 评论
分享
牛客网
牛客企业服务