【算法题】最大的奇约数

本文介绍了一种高效算法,用于求解一系列幸运数的总和,通过找到递推规律将时间复杂度从O(n)降低到O(logn)。文章提供了具体的数学推导过程及Java代码实现。

题目来源:网易

我的解法:

         一开用的是始逐项求最大奇数然后相加的解法,由于后面几个测试用例的n比较大,所以运行超时了,这样就不得不从中找规律来解。

        不难发现,当x为奇数时,f(x)=x。

        当n为奇数,s(n) = f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + .... + n = (1 + 3 + 5 + 7 + ...+ n) + (f(2) + f(4) + f(6) + ... + f(n- 1))

        令k = (n+1)/2, 根据等差数列的性质

        s(n) = k*(1 + n)/2 = k^2 + (2 + 4 + 6 + .. + n-1) = k^2 + (f(1) + f(2) + f(3) + ... +f((n-1)/2))

        s(n) = k^2 + s((n-1)/2) = k ^ 2 + s(n/2)  (这里因为n为奇数,除法只取整数部分,因此(n-1)/2和n/2是一样的)

        当n为偶数,能够得出同样的递推公式。

        显然,这个算法的时间复杂度从原本的O(n)降到了O(logn)。


代码实现

public class LuckyNumber {

    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        int n = s.nextInt();
        System.out.println(oddSum(n));
    }

    public static long oddSum(int n) {
        if (n == 0) {
            return 0;
        }
        long k = (n + 1) >> 1;
        return k * k + oddSum(n / 2); //如果不用递归,这段也能转化成循环
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值