算法训练-数学

数学

leetcode238. 除自身以外数组的乘积

法一:乘积 = 当前数左边的乘积 * 当前数右边的乘积

 leetcode169. 多数元素

法一:排序

法二:摩尔投票

leetcode343. 整数拆分

法一:数学推导

leetcode89. 格雷编码

法一:归纳法 

 leetcode1823. 找出游戏的获胜者

法一:递归

法二:迭代

leetcode400. 第 N 位数字

法一:直接计算 

leetcode233. 数字 1 的个数

法一:逐位相加


leetcode238. 除自身以外数组的乘积

238. 除自身以外数组的乘积icon-default.png?t=O83Ahttps://leetcode.cn/problems/product-of-array-except-self/

法一:乘积 = 当前数左边的乘积 * 当前数右边的乘积

public class Method01 {

    public int[] productExceptSelf(int[] nums) {
        int n = nums.length; // 获取输入数组的长度
        int[] res = new int[n]; // 初始化结果数组
        res[0] = 1; // 有效地设置 res[0] 的初始值为 1

        // 第一个循环:计算每个位置左侧所有元素的乘积
        for (int i = 1; i < n; i++) {
            res[i] = res[i - 1] * nums[i - 1]; // res[i] 是 nums[0] 到 nums[i-1] 的乘积
        }

        int right = 1; // 初始化右侧乘积为 1

        // 第二个循环:从右到左,计算每个位置右侧所有元素的乘积,并与左侧乘积相乘
        for (int i = n - 2; i >= 0; i--) {
            right *= nums[i + 1]; // 计算右侧元素的乘积
            res[i] *= right; // 将右侧乘积与左侧乘积相乘,存储结果到 res[i]
        }

        return res; // 返回最终结果数组
    }
}

 leetcode169. 多数元素

169. 多数元素icon-default.png?t=O83Ahttps://leetcode.cn/problems/majority-element/

法一:排序

public class Method01 {
    public int majorityElement(int[] nums) {
        Arrays.sort(nums);
        return nums[nums.length/2];
    }
}

法二:摩尔投票

public class Method02 {

    public int majorityElement(int[] nums) {
        int count = 0; // 计数器,初始化为 0
        int major_number = 0; // 存储当前的主要元素

        // 遍历数组中的每一个元素
        for (int num : nums) {
            // 当计数器为 0 时,更新主要元素为当前元素
            if (count == 0) {
                major_number = num; // 更新主要元素
                count++; // 计数器加 1
            } else {
                // 如果当前元素与主要元素相同,增加计数
                if (num == major_number) {
                    count++; // 计数器加 1
                } else {
                    count--; // 否则减少计数
                }
            }
        }

        return major_number; // 返回最终的主要元素
    }
}

leetcode343. 整数拆分

343. 整数拆分icon-default.png?t=O83Ahttps://leetcode.cn/problems/integer-break/

法一:数学推导

public class Method01 {

    public int integerBreak(int n) {
        // 当 n 小于等于 3 时,返回 n - 1
        // 因为 2 只能拆分成 1 + 1,3 只能拆分成 1 + 2
        if (n <= 3) return n - 1;

        int beishu = n / 3; // 计算可以拆分为多少个 3
        int yushu = n % 3;  // 计算 n 除以 3 的余数

        // 根据余数的值计算结果:
        // - 如果余数为 0,返回 3^(beishu-1) * 3
        // - 如果余数为 1,返回 3^(beishu-1) * 4
        // - 如果余数为 2,返回 3^(beishu-1) * 6
        return (int) Math.pow(3, beishu - 1) * (yushu == 0 ? 3 : yushu == 1 ? 4 : 6);
    }
}

leetcode89. 格雷编码

89. 格雷编码icon-default.png?t=O83Ahttps://leetcode.cn/problems/gray-code/

法一:归纳法 

public class Method01 {

    public List<Integer> grayCode(int n) {
        List<Integer> res = new ArrayList<>(); // 创建一个列表用于存储结果
        res.add(0); // 将 0 添加到结果中,表示 Gray 码的起始值
        int head = 1; // 初始化头部值为 1

        // 外层循环迭代 n 次,每次增加一个二进制位
        for (int i = 0; i < n; i++) {
            int size = res.size(); // 当前结果列表的大小
            // 内层循环反向遍历已有结果列表,将新生成的 Gray 码添加到结果列表中
            for (int j = size - 1; j >= 0; j--) {
                res.add(res.get(j) + head); // 根据当前的头部值生成新的 Gray 码
            }
            head <<= 1; // 将头部值左移一位,以便为下一个二进制位生成 Gray 码
        }

        return res; // 返回最终生成的 Gray 码列表
    }
}

 leetcode1823. 找出游戏的获胜者

1823. 找出游戏的获胜者icon-default.png?t=O83Ahttps://leetcode.cn/problems/find-the-winner-of-the-circular-game/

法一:递归

public class Method01 {
    public int findTheWinner(int n, int k) {
        if (n == 1) {
            return 1; // 当只有一个人时,赢家是第一人
        }
        // 使用递归公式计算赢家
        return (k + findTheWinner(n - 1, k) - 1) % n + 1;
    }
}

法二:迭代

public class Method02 {

    public int findTheWinner(int n, int k) {
        int winner = 1; // 初始化赢家,假设在第一个人中选择赢家

        // 从第二个人开始迭代到第 n 个人
        for (int i = 2; i <= n; i++) {
            // 根据当前人数和步长计算赢家的位置
            winner = (k + winner - 1) % i + 1;
        }

        return winner; // 返回最终赢家
    }
}

leetcode400. 第 N 位数字

400. 第 N 位数字icon-default.png?t=O83Ahttps://leetcode.cn/problems/nth-digit/

法一:直接计算 

public class Method01 {
    // 该方法用于找到第n个数字
    public int findNthDigit(int n) {
        // count 表示当前位数下的数字总数
        long count = 9;
        // digit 表示当前数字的位数
        int digit = 1;
        // start 表示当前位数下的第一个数字
        long start = 1;

        // 当 n 大于当前位数下的数字总数时,继续循环
        while (n > count) {
            // 从 n 中减去当前位数下的数字总数
            n -= count;
            // 将 start 更新为下一个位数下的第一个数字
            start *= 10;
            // 将 digit 增加1,并更新 count 为下一个位数下的数字总数
            count = ++digit * 9 * start;
        }

        // 计算出第n个数字所在的数字
        long num = start + (n - 1) / digit;
        // 计算出第n个数字在 num 中的位置
        int index = (n - 1) % digit;
        // 返回 num 中对应位置的数字
        return Long.toString(num).charAt(index) - '0';
    }
}

leetcode233. 数字 1 的个数

233. 数字 1 的个数icon-default.png?t=O83Ahttps://leetcode.cn/problems/number-of-digit-one/

法一:逐位相加

public class Method01 {
    // 计算从1到n的所有整数中,数字1出现的总次数
    public int countDigitOne(int n) {
        int digit = 1, res = 0; // digit表示当前处理的位数(个位、十位、百位等),res用于存储最终的结果
        int high = n / 10, cur = n % 10, low = 0; // high表示当前位的高位部分,cur表示当前位,low表示当前位的低位部分

        // 当high和cur都不为0时,循环继续
        while (high != 0 || cur != 0) {
            // 根据当前位的值更新结果
            if (cur == 0) {
                // 如果当前位为0,1出现的次数为high * digit
                res += high * digit;
            } else if (cur == 1) {
                // 如果当前位为1,1出现的次数为high * digit + low + 1
                res += high * digit + low + 1;
            } else {
                // 如果当前位大于1,1出现的次数为(high + 1) * digit
                res += (high + 1) * digit;
            }

            // 更新低位和当前位
            low += cur * digit; // 更新低位部分
            cur = high % 10; // 更新当前位
            high /= 10; // 更新高位部分
            digit *= 10; // 更新当前位数
        }

        // 返回计算得到的1出现的次数
        return res;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值