首页 > 编程语言 >【优选算法】(第十四篇)

【优选算法】(第十四篇)

时间:2024-10-01 14:20:51浏览次数:9  
标签:优选 下标 nums int 元素 rprod 算法 数组 第十四

目录

寻找数组的中⼼下标(easy)

题目解析

讲解算法原理

编写代码

除⾃⾝以外数组的乘积(medium)

题目解析

讲解算法原理

编写代码


寻找数组的中⼼下标(easy)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给你⼀个整数数组nums,请计算数组的中⼼下标。
数组中⼼下标是数组的⼀个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中⼼下标位于数组最左端,那么左侧数之和视为0,因为在下标的左侧不存在元素。这⼀点对于中⼼下标位于数组最右端同样适⽤。
如果数组有多个中⼼下标,应该返回最靠近左边的那⼀个。如果数组不存在中⼼下标,返回-1。
⽰例1:输⼊:nums=[1,7,3,6,5,6]输出:3
解释:中⼼下标是3。左侧数之和sum=nums[0]+nums[1]+nums[2]=1+7+3=11,右侧数之和sum=nums[4]+nums[5]=5+6=11,⼆者相等。
⽰例2:输⼊:nums=[1,2,3]输出:-1
解释:数组中不存在满⾜此条件的中⼼下标。
⽰例3:输⼊:nums=[2,1,-1]输出:0
解释:中⼼下标是0。左侧数之和sum=0,(下标0左侧不存在元素),右侧数之和sum=nums[1]+nums[2]=1+-1=0。
提⽰:1<=nums.length<=10^4-1000<=nums[i]<=1000

讲解算法原理

解法(前缀和):
算法思路:
从中⼼下标的定义可知,除中⼼下标的元素外,该元素左边的「前缀和」等于该元素右边的「后缀和」。
▪ 因此,我们可以先预处理出来两个数组,⼀个表⽰前缀和,另⼀个表⽰后缀和。▪ 然后,我们可以⽤⼀个 for 循环枚举可能的中⼼下标,判断每⼀个位置的「前缀和」以及
「后缀和」,如果⼆者相等,就返回当前下标。

编写代码

c++算法代码:

class Solution {
public:
 int pivotIndex(vector<int>& nums) {
 // lsum[i] 表⽰:[0, i - 1] 区间所有元素的和 // rsum[i] 表⽰:[i + 1, n - 1] 区间所有元素的和 int n = nums.size();
 vector<int> lsum(n), rsum(n);
 // 预处理前缀和后缀和数组
 for(int i = 1; i < n; i++)
 lsum[i] = lsum[i - 1] + nums[i - 1];
 for(int i = n - 2; i >= 0; i--)
 rsum[i] = rsum[i + 1] + nums[i + 1];
 // 判断
 for(int i = 0; i < n; i++)
 if(lsum[i] == rsum[i])
 return i;
 return -1;
 }
};

java算法代码:

class Solution
{
 public int pivotIndex(int[] nums) 
 {
 // lsum[i] 表⽰:[0, i - 1] 区间所有元素的和 // rsum[i] 表⽰:[i + 1, n - 1] 区间所有元素的和 int n = nums.length;
 int[] lsum = new int[n];
 int[] rsum = new int[n];
 // 预处理前缀和后缀和数组
 for(int i = 1; i < n; i++)
 lsum[i] = lsum[i - 1] + nums[i - 1];
 for(int i = n - 2; i >= 0; i--)
 rsum[i] = rsum[i + 1] + nums[i + 1];
 // 判断
 for(int i = 0; i < n; i++)
 if(lsum[i] == rsum[i])
 return i;
 return -1;
 }
}

除⾃⾝以外数组的乘积(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给你⼀个整数数组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
保证数组nums之中任意元素的全部前缀元素和后缀的乘积都在32位整数范围内
进阶:你可以在O(1)的额外空间复杂度内完成这个题⽬吗?(出于对空间复杂度分析的⽬的,输出数组不被视为额外空间。)

讲解算法原理

解法(前缀和数组):
算法思路:
注意题⽬的要求,不能使⽤除法,并且要在 O(N) 的时间复杂度内完成该题。那么我们就不能使⽤暴⼒的解法,以及求出整个数组的乘积,然后除以单个元素的⽅法。
继续分析,根据题意,对于每⼀个位置的最终结果 ret[i] ,它是由两部分组成的:
i. nums[0] * nums[1] * nums[2] * ... * nums[i - 1]
ii. nums[i + 1] * nums[i + 2] * ... * nums[n - 1]
于是,我们可以利⽤前缀和的思想,使⽤两个数组post和suf,分别处理出来两个信息:
i. post表⽰:i位置之前的所有元素,即 [0, i - 1] 区间内所有元素的前缀乘积,ii. suf表⽰:i位置之后的所有元素,即 [i + 1, n - 1] 区间内所有元素的后缀乘积
然后再处理最终结果。

编写代码

c++算法代码:

class Solution
{
public:
 vector<int> productExceptSelf(vector<int>& nums) 
 {
 // lprod 表⽰:[0, i - 1] 区间内所有元素的乘积 // rprod 表⽰:[i + 1, n - 1] 区间内所有元素的乘积 int n = nums.size();
 vector<int> lprod(n + 1), rprod(n + 1);
 lprod[0] = 1, rprod[n - 1] = 1;
 
 // 预处理前缀积以及后缀积
 for(int i = 1; i < n; i++)
 lprod[i] = lprod[i - 1] * nums[i - 1];
 for(int i = n - 2; i >= 0; i--)
 rprod[i] = rprod[i + 1] * nums[i + 1];
 
 // 处理结果数组
 vector<int> ret(n);
 for(int i = 0; i < n; i++)
 ret[i] = lprod[i] * rprod[i];
 return ret;
 }
};

java算法代码:

class Solution {
 public int[] productExceptSelf(int[] nums) {
 // lprod 表⽰:[0, i - 1] 区间内所有元素的乘积 // rprod 表⽰:[i + 1, n - 1] 区间内所有元素的乘积 int n = nums.length;
 int[] lprod = new int[n];
 int[] rprod = new int[n];
 lprod[0] = 1; rprod[n - 1] = 1;
 
 // 预处理前缀积以及后缀积
 for(int i = 1; i < n; i++)
 lprod[i] = lprod[i - 1] * nums[i - 1];
 for(int i = n - 2; i >= 0; i--)
 rprod[i] = rprod[i + 1] * nums[i + 1];
 
 // 处理结果数组
 int[] ret = new int[n];
 for(int i = 0; i < n; i++)
 ret[i] = lprod[i] * rprod[i];
 return ret;
 }
}

标签:优选,下标,nums,int,元素,rprod,算法,数组,第十四
From: https://blog.csdn.net/weixin_73861555/article/details/142670616

相关文章