剑指offer[14-1、14-2、15]

本文深入探讨了两个经典的算法问题:“剪绳子”问题的两种解法,包括暴力遍历+备忘录法和贪心算法+数学推导,以及如何在大数情况下求解;“二进制中1的个数”问题,提供了两种高效算法,分别是遍历二进制位和利用n-1二进制位与n的不同来统计1的个数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面试题14-1剪绳子

题目:

给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m] 。请问 k[0]k[1]…*k[m] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18

解法:

思路一:

暴力遍历+备忘录法减少运算量

// 暴力解法+备忘录减少运算量
class Solution {
    public int cuttingRope(int n) {
        int[] f=new int[n+1];
        return mem(f,n);
        
    }
    public int mem(int[] f,int n){
        if(f[n]!=0){
            return f[n];
        }
        if (n == 2) return 1;
        int res = -1;
        for (int i = 1; i <= n - 1; i++) {
            res = Math.max(res, Math.max(i * (n - i), i * mem(f,n - i)));
        }
        f[n]=res;
        return res;
    }
}
# 使用辅助函数
class Solution:
    def cuttingRope(self, n: int) -> int:
        def memoize(n):
            if n == 2: return 1
            if f[n] != 0: # 如果f[n]已经计算过,直接返回避免重复计算
                return f[n]
            res = -1
            for i in range(1, n):
                res = max(res, max(i * (n - i),i * memoize(n - i)))
            f[n] = res
            return res

        f = [0 for _ in range(n + 1)]
        return memoize(n)

思路二:

贪心算法+数学推导:
① 当所有绳段长度相等时,乘积最大。② 最优的绳段长度为 3。
在这里插入图片描述

class Solution {
    public int cuttingRope(int n) {
        if(n<=3) return n-1;
        int i=n%3,j=n/3;
        if(i==0) return (int)Math.pow(3,j);
        else if(i==1) return (int)Math.pow(3,j-1)*4;
        return (int)Math.pow(3,j)*2;
    }
}
class Solution:
    def cuttingRope(self, n: int) -> int:
        if n<=3: return n-1
        i=n%3
        j=n//3
        if i==0: return int(math.pow(3,j))
        elif i==1: return int(math.pow(3,j-1)*4)
        return int(math.pow(3,j)*2)

面试题14-2 剪绳子||

题目:

给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m] 。请问 k[0]k[1]…*k[m] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

解法:

添加大数求余:循环求余||快速幂求余算法

//循环求余
class Solution {
    public int cuttingRope(int n) {
        if(n <= 3) return n - 1;
        int b = n % 3, p = 1000000007,a=n/3;
        long rem = 1, x = 3;
        // 循环求余数
        for(int i=1; i<a; i++) {
            rem = (rem * x) % p;
        }
        if(b == 0) return (int)(rem * 3%p);
        if(b == 1) return (int)(rem * 4%p );
        return (int)(rem * 6%p );
    }
}
//快速幂求余
class Solution {
    public int cuttingRope(int n) {
        if(n <= 3) return n - 1;
        int b = n % 3, p = 1000000007;
        long rem = 1, x = 3;

        for(int a = n / 3 - 1; a > 0; a /= 2) {
            if(a % 2 == 1) rem = (rem * x) % p;
            x = (x * x) % p;
        }
        if(b == 0) return (int)(rem * 3 % p);
        if(b == 1) return (int)(rem * 4 % p);
        return (int)(rem * 6 % p);
    }
}
class Solution:
    def cuttingRope(self, n: int) -> int:
        if n <= 3: return n - 1
        a, b, p, x, rem = n // 3 - 1, n % 3, 1000000007, 3 , 1
        while a > 0:
            if a % 2: rem = (rem * x) % p
            x = x ** 2 % p
            a //= 2
        if b == 0: return (rem * 3) % p # = 3^(a+1) % p
        if b == 1: return (rem * 4) % p # = 3^a * 4 % p
        return (rem * 6) % p # = 3^(a+1) * 2  % p
# 由于语言特性,Python 可以不考虑大数越界问题
class Solution:
    def cuttingRope(self, n: int) -> int:
        if n <= 3: return n - 1
        a, b, p = n // 3, n % 3, 1000000007
        if b == 0: return 3 ** a % p
        if b == 1: return 3 ** (a - 1) * 4 % p
        return 3 ** a * 2 % p

面试题15 二进制中的一个数

题目:

请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。

解法:

思路一:

依次从右向左遍历二进制位,统计出一的个数;

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
       // 普通遍历法
        int res=0;
        while(n!=0){
            res+=n&1;
            n>>>=1;
        }
        return res;
        }
}        
class Solution:
    def hammingWeight(self, n: int) -> int:
		#普通遍历法
        res=0
        while n:
            res+=n&1
            n>>=1
        return res

思路二:

利用n-1二进制位与n之间的不同,依次统计1的个数
在这里插入图片描述

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int res=0;
        while(n!=0){
            res++;
            n=n&(n-1);
        }
        return res;
    }
}
class Solution:
    def hammingWeight(self, n: int) -> int:
        # 借助n-1
        res=0
        while n:
            res+=1
            n=n&(n-1)
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值