【力扣Hot 100】普通数组2

3. 轮转数组

给定一个整数数组 nums,将数组中的元素向右轮转 k **个位置,其中 k **是非负数。

示例 1:

复制代码
输入: nums = [1,2,3,4,5,6,7], k = 3
输出:[5,6,7,1,2,3,4]解释:
向右轮转 1 步:[7,1,2,3,4,5,6]
向右轮转 2 步:[6,7,1,2,3,4,5]
向右轮转 3 步:[5,6,7,1,2,3,4]

示例 2:

复制代码
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

提示:

  • 1 <= nums.length <= 105
  • 231 <= nums[i] <= 231 - 1
  • 0 <= k <= 105

题解

使用反转数组的方法。

别人的解答:

kotlin 复制代码
nums = "----->-->"; k =3
result = "-->----->";

reverse "----->-->" we can get "<--<-----"
reverse "<--" we can get "--><-----"
reverse "<-----" we can get "-->----->"
this visualization help me figure it out :)

看图就能理解了。

反转数组可以定义两个指针bg, ed,一个指向数组开始,一个指向数组末尾,交换它们直到重合或相交。

cpp 复制代码
class Solution {
public:
    void reverse(vector<int>& nums, int bg, int ed) {
        while(bg < ed) {
            swap(nums[bg], nums[ed]);
            bg ++;
            ed --;
        }
    }
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k %= n;
        reverse(nums, 0, n - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, n - 1);
    }
};

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

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

请 **不要使用除法,**且在 O(n) 时间复杂度内完成此题。

示例 1:

复制代码
输入: nums =[1,2,3,4]输出:[24,12,8,6]

示例 2:

复制代码
输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]

提示:

  • 2 <= nums.length <= 105
  • 30 <= nums[i] <= 30
  • 输入 保证 数组 answer[i]32 位 整数范围内

**进阶:**你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)

题解

非常明显的做法是建立一个前缀积数组,一个后缀积数组。输出的时候输出它们的乘积即可。

前缀积数组 f[i],表示以 i - 1 结尾的前缀积

后缀积数组 g[i],表示以 i + 1 结尾的后缀积

那么 f[i + 1] = f[i] * nums[i] , g[i - 1] = g[i] * nums[i]

cpp 复制代码
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n + 1), g(n + 1);
        f[0] = 1;
        g[n - 1] = 1;
        for(int i = 0; i < n; i ++ ) {
            f[i + 1] = f[i] * nums[i];
        }
        for(int i = n - 1; i > 0; i -- ) {
            g[i - 1] = g[i] * nums[i];
        }
        
        vector<int> ans(n);
        for(int i = 0; i < n; i ++ ) {
            ans[i] = f[i] * g[i];
        }
        return ans;
    }
};

由于输出数组不计入空间复杂度,所以还可以继续优化。先把输出数组当作 L 数组来计算,然后再动态构造 R 数组得到结果。

cpp 复制代码
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> ans(n);
        ans[0] = 1;
        for(int i = 1; i <= n; i ++ ) {
            ans[i] = ans[i - 1] * nums[i - 1];
        }

        int r = 1;
        for(int i = n - 1; i >= 0; i --) {
            ans[i] = ans[i] * r;
            r *= nums[i];
        }

        return ans;
    }
};
相关推荐
飞机和胖和黄1 小时前
考研之王道C语言第三周
c语言·数据结构·考研
yyy(十一月限定版)1 小时前
寒假集训4——二分排序
算法
星火开发设计1 小时前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
醉颜凉1 小时前
【LeetCode】打家劫舍III
c语言·算法·leetcode·树 深度优先搜索·动态规划 二叉树
达文汐1 小时前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗1 小时前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
User_芊芊君子1 小时前
【LeetCode经典题解】搞定二叉树最近公共祖先:递归法+栈存路径法,附代码实现
算法·leetcode·职场和发展
培风图南以星河揽胜1 小时前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划
算法_小学生1 小时前
LeetCode 热题 100(分享最简单易懂的Python代码!)
python·算法·leetcode
执着2591 小时前
力扣hot100 - 234、回文链表
算法·leetcode·链表