数组系列问题
Leetcode 238. 除自身以外数组的乘积【中等】
题意理解:
一个整数数组,求每个位置上出该元素外其余元素的乘积。
我们可以先求出所有元素的乘积,再除以当前位置的元素即为所求。
特别的是0元素,0不能做被除数,所以对于0元素需要额外的讨论。
解题思路:
使用product计算所有非零元素的和,使用zeroCount统计0元素的个数
用result[] 数组来统计结果
zeroCount==0时,result[i]=product/nums[i]
zeroCount==1时,除了0元素对应的result[i]=product外,其余result[i]=0
zeroCount==2时,剩余数中总有一个0元素,故result[i]=0
1.解题
class Solution {
public int[] productExceptSelf(int[] nums) {
int len=nums.length;
int zeroCount=0;
int product=1;
for(int i=0;i<len;i++){
if(nums[i]==0){
zeroCount++;
}else{
product*=nums[i];
}
}
int[] result=new int[len];
for(int i=0;i<len;i++){
if(zeroCount==0){
result[i]=product/nums[i];
}else if(zeroCount>1){
result[i]=0;
}else if(zeroCount==1){
if(nums[i]==0){
result[i]=product;
}else{
result[i]=0;
}
}
}
return result;
}
}
2.复杂度分析
时间复杂度: O(n) 遍历数组的时间
空间复杂度: O(n) 数组的空间损耗
Leetcode 41. 缺失的第一个正数【困难】
题意理解:
数组未排序,其中是否有最小正整数
这个题目有个非常巧妙的地方。一个长度为n的数组,求最小出现的正整数。
则如果这个数组中不存在缺失的最小正整数,则其应该存储的是1-n的n个正整数。
当且仅当数组中存在<1或>n的数时,肯定有某个连续的地方被打断了。
解题思路:
1.标记出现的元素
如果nums中没有1,则缺失的第一个元素就是1
若nums中包含1,此时,将nums中<1||>n的元素替换为1
从头开始遍历数组,其中,某个元素出现,则将对应位置(i-1)的元素置换为负数。
如果当前位置已经是负数,则对应位置仍保留位负数。
最后从头遍历数组,第一个正数的坐标+1即为所求。
若,没有找到第一个正整数,则说明数组1-n连续,下一个最小正整数为n+1
2.置换
将nums中[1,n]的元素替换为对饮的坐标上
遍历nums数组,其中第一个元素和坐标不对应的位置即为所求
while(nums[i]>0&&nums[i]<len&&nums[nums[i]-1]!=nums[i])
额外的注意,当且仅当nums[nums[i]-1]==nums[i]时,while可能造成死循环。
1.解题【标记未出现的元素】
class Solution {
public int firstMissingPositive(int[] nums) {
int len=nums.length;
//数组中没有1,则缺失的第一个正整数为1
boolean flag=true;
for(int i=0;i<len;i++){
if(nums[i]==1) flag=false;
//将负数和0置换为0,方便后续操作
if(nums[i]<1||nums[i]>len) nums[i]=1;
}
if(flag) return 1;
//若i位置上的数字出现过,则将对应位置置为负数
for(int i=0;i<len;i++){
nums[Math.abs(nums[i])-1]=-1*Math.abs(nums[Math.abs(nums[i])-1]);
}
//查找第一个为负的元素
for(int i=0;i<len;i++){
if(nums[i]>0) return i+1;
}
//如何没找到第一个正整数,则返回n+1
return len+1;
}
}
1.解题【置换】
class Solution {
public int firstMissingPositive(int[] nums) {
int len=nums.length;
//将1-n之间的元素置换到对应坐标位置上
for(int i=0;i<len;i++){
while(nums[i]>0&&nums[i]<len&&nums[nums[i]-1]!=nums[i]){
int temp=nums[i];
System.out.println(i+" "+temp);
nums[i]=nums[temp-1];
nums[temp-1]=temp;
}
}
//查找第一个为负的元素
for(int i=0;i<len;i++){
if(nums[i]!=i+1) return i+1;
}
//如何没找到第一个正整数,则返回n+1
return len+1;
}
}
2.复杂度分析
时间复杂度:O(n) 时间复杂度3个for循环的时间损耗
空间复杂度:O(1) 存储结果的空间损耗