每日力扣刷题day02(从零开始版)

2024.5.23(5题)

1929. 数组串联

此题与昨天的1470.重新排练数组很像,一个是双指针从左边和中间交替赋值给新的,这个是赋值给新数组的左边和中间索引的位置

题目链接

给你一个长度为 n 的整数数组 nums 。请你构建一个长度为 2n 的答案数组 ans ,数组下标 从 0 开始计数 ,对于所有 0 <= i < ni ,满足下述所有要求:

  • ans[i] == nums[i]
  • ans[i + n] == nums[i]

具体而言,ans 由两个 nums 数组 串联 形成。

返回数组 ans

示例 1:

输入:nums = [1,2,1]
输出:[1,2,1,1,2,1]
解释:数组 ans 按下述方式形成:
- ans = [nums[0],nums[1],nums[2],nums[0],nums[1],nums[2]]
- ans = [1,2,1,1,2,1]

示例 2:

输入:nums = [1,3,2,1]
输出:[1,3,2,1,1,3,2,1]
解释:数组 ans 按下述方式形成:
- ans = [nums[0],nums[1],nums[2],nums[3],nums[0],nums[1],nums[2],nums[3]]
- ans = [1,3,2,1,1,3,2,1]

提示:

  • n == nums.length
  • 1 <= n <= 1000
  • 1 <= nums[i] <= 1000
题解一
class Solution {
    public int[] getConcatenation(int[] nums) {
        int n = nums.length;
        int[] ans = new int[2 * n];
        for (int i = 0; i < n; i++) {
            ans[i + n] = ans[i] = nums[i];
        }
        return ans;
    }
}
  • 要返回的数组中,前后两部分是一样的,同时赋值就行了
题解二
class Solution {
    public int[] getConcatenation(int[] nums) {
        int n = nums.length;
        int[] ans = Arrays.copyOf(nums, n*2);
        System.arraycopy(nums, 0, ans, n, n);
        return ans;
    }
}
  • 使用Arrays.copyOf方法创建了一个新数组ansArrays.copyOf方法的第一个参数是源数组nums,第二个参数是新数组的长度(这里是n * 2)。这个方法会复制源数组的元素到新数组中

  • 使用System.arraycopy方法将nums数组的一部分复制到ans数组的指定位置。

    System.arraycopy方法的参数依次为:

    • nums:源数组。

    • 0:源数组的起始位置(从索引0开始)。

    • ans:目标数组。

    • n:目标数组的起始位置(从索引n开始)。

    • n:要复制的元素数量。

1281. 整数的各位积和之差

题目关键在于如何取得整数的每一位上的数

题目链接

给你一个整数 n,请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。

示例 1:

输入:n = 234
输出:15 
解释:
各位数之积 = 2 * 3 * 4 = 24 
各位数之和 = 2 + 3 + 4 = 9 
结果 = 24 - 9 = 15

示例 2:

输入:n = 4421
输出:21
解释: 
各位数之积 = 4 * 4 * 2 * 1 = 32 
各位数之和 = 4 + 4 + 2 + 1 = 11 
结果 = 32 - 11 = 21

提示:

  • 1 <= n <= 10^5
题解一
class Solution {
    public int subtractProductAndSum(int n) {
        int sum = 0;
        int product = 1;
        int index = 0;
        while (n != 0) {
            index = n % 10;
            sum += index;
            product *= index;
            n /= 10;
        }
        return product - sum;
    }
}
  • 传过来的是一个整数,我们只要取得这个整数的每一位上的数就行了
  • 使用取余运算符(%)来计算整数n的最后一位数字。取余运算符返回除法运算的余数。n % 10 是获取整数n的个位数。
  • 使用除法赋值运算符(/=)将整数n除以10,并将结果赋值回n。整数除法会丢弃小数部分,只保留商的整数部分。作用是去掉整数n的最后一位数字。
题解二
class Solution {
    public int subtractProductAndSum(int n) {
        String[] digits = Integer.toString(n).split("");
        
        int product = 1;
        int sum = 0;

        for (String digit : digits) {
            int num = Integer.parseInt(digit);
            product *= num;
            sum += num;
        }
        return product - sum;
    }
}
  • 将整数n转换为字符串,然后使用split方法将字符串拆分为字符数组。每个字符表示一个数字。
  • 不推荐使用这个方法,更慢,并且毫无技巧。

1137. 第 N 个泰波那契数

此题是一个简单的动态规划题,题目给出了动态规划中最重要的转移方程,是动态规划的入门题

题目链接

泰波那契序列 Tn 定义如下:

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

示例 1:

输入:n = 4
输出:4
解释:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4

示例 2:

输入:n = 25
输出:1389537

提示:

  • 0 <= n <= 37
  • 答案保证是一个 32 位整数,即 answer <= 2^31 - 1
题解一
class Solution {
    int[] cache = new int[40];
    public int tribonacci(int n) {
        if (n == 0) return 0;
        if (n == 1 || n == 2) return 1;
        if (cache[n] != 0) return cache[n];
        cache[n] = tribonacci(n - 1) + tribonacci(n - 2) + tribonacci(n - 3); 
        return cache[n];
    }
}
  • 跟经典的斐波那契数列一样,递归很好理解
  • 递归实现可以直接使用定义的递推关系,为了避免重复计算,需要用一个数组来存储已经计算过的结果(记忆化)。题目的数据范围是 [0,37],我们直接创建40的长度就够了。
题解二
class Solution {
    public int tribonacci(int n) {
        if (n == 0)
            return 0;
        if (n == 1 || n == 2)
            return 1;

        int prev3 = 0, prev2 = 1, prev1 = 1;
        int current = 0;
        for (int i = 3; i <= n; i++) {
            current = prev1 + prev2 + prev3;
            prev3 = prev2;
            prev2 = prev1;
            prev1 = current;
        }
        return current;
    }
}
  1. 初始条件
    • T0 = 0
    • T1 = 1
    • T2 = 1
  2. 转移方程
    • 对于 n >= 3,有 Tn = Tn-1 + Tn-2 + Tn-3
  3. 迭代过程
    • 从 T3 开始,依次计算每一个 Tn,直到计算到第 n 个泰波那契数。
    • 需要三个变量来存储前面三个数的值,逐步更新它们。

2413. 最小偶倍速

给出两个数的最小公倍数的通解

题目链接

给你一个正整数 n ,返回 2n 的最小公倍数(正整数)。

示例 1:

输入:n = 5
输出:10
解释:5 和 2 的最小公倍数是 10 。

示例 2:

输入:n = 6
输出:6
解释:6 和 2 的最小公倍数是 6 。注意数字会是它自身的倍数。

提示:

  • 1 <= n <= 150
题解一
class Solution {
    public int smallestEvenMultiple(int n) {
        return n % 2 == 0 ? n : n * 2;
    }
}
  • 如果 n 为偶数,那么 2 和 n 的最小公倍数就是 n 本身。否则,2 和 n 的最小公倍数就是 n×2。
题解二
public static int lcm(int a, int b) {
        return (a * b) / gcd(a, b);
    }

public static int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

要计算两个数的最小公倍数 (LCM),我们可以利用最大公约数 (GCD)。最小公倍数可以通过以下公式计算:
[ a , b ] = a b gcd ⁡ ( a , b ) [a, b] = \frac{ab}{\gcd(a, b)} [a,b]=gcd(a,b)ab
最大公约数 (GCD)求法:

  • gcd 方法使用欧几里得算法来计算两个数的最大公约数。
  • 通过不断取余数更新 a 和 b 的值,直到 b 为 0,此时 a 就是 GCD。

2778. 特殊元素平方和

两种解法,优化小技巧

题目链接

给你一个下标从 1 开始、长度为 n 的整数数组 nums

nums 中的元素 nums[i] 而言,如果 n 能够被 i 整除,即 n % i == 0 ,则认为 num[i] 是一个 特殊元素

返回 nums 中所有 特殊元素平方和

示例 1:

输入:nums = [1,2,3,4]
输出:21
解释:nums 中共有 3 个特殊元素:nums[1],因为 4 被 1 整除;nums[2],因为 4 被 2 整除;以及 nums[4],因为 4 被 4 整除。 
因此,nums 中所有特殊元素的平方和等于 nums[1] * nums[1] + nums[2] * nums[2] + nums[4] * nums[4] = 1 * 1 + 2 * 2 + 4 * 4 = 21 。  

示例 2:

输入:nums = [2,7,1,19,18,3]
输出:63
解释:nums 中共有 4 个特殊元素:nums[1],因为 6 被 1 整除;nums[2] ,因为 6 被 2 整除;nums[3],因为 6 被 3 整除;以及 nums[6],因为 6 被 6 整除。 
因此,nums 中所有特殊元素的平方和等于 nums[1] * nums[1] + nums[2] * nums[2] + nums[3] * nums[3] + nums[6] * nums[6] = 2 * 2 + 7 * 7 + 1 * 1 + 3 * 3 = 63 。 

提示:

  • 1 <= nums.length == n <= 50
  • 1 <= nums[i] <= 50
题解一
class Solution {
    public int sumOfSquares(int[] nums) {
        int n = nums.length;
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (n % (i + 1) == 0) {
                ans += nums[i] * nums[i];
            }
        }
        return ans;
    }
}
  • 遍历一遍,根据题目要求加一个 if 就行了
  • 注意的是,数组的下标从 1 开始,取余的时候给 i + 1 就好了
题解二
class Solution {
public int sumOfSquares(int[] nums) {
        int n = nums.length;
        int ans = 0;

        for (int i = 1; i * i <= n; i++) {
            if (n % i == 0) {
                ans += nums[i - 1] * nums[i - 1];

                if (i != n / i) {
                    ans += nums[(n / i) - 1] * nums[(n / i) - 1];
                }
            }
        }
        return ans;
    }
}
  • 当 i 是 n 的因子,那么 n / i 也是 n 的因子,只需要遍历 √n 之内的就可以了

    对于一个正整数 𝑛,其因子成对出现。如果 𝑖 是 𝑛 的因子,那么 𝑛 / 𝑖 也是 𝑛 的因子。

    例如,对于 𝑛=36:

    • 因子对包括 (1, 36)、(2, 18)、(3, 12)、(4, 9)、(6, 6)。

    这些因子对的特征是:每对因子中的一个数小于或等于 𝑛,另一个数大于或等于 𝑛。当 𝑖 增加到超过 𝑛 时,相应的因子对中的较大数已经被包含在前面的较小数中,因此没有必要再检查大于 𝑛 的数。

  • 相比题解一,这个时间复杂度为O(√n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

全栈ing小甘

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

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

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

打赏作者

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

抵扣说明:

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

余额充值