3月10日
第一次做感觉很简单,但没有考虑时间复杂度的问题,直接用两个for嵌套,挨个查找,结果时间复杂度过高,为O(n*n),超出时间限制。
//挨个遍历超出时间限制 o(n*n)
int len = nums.size();
int flag=-1;
int n=0;
for(int i=0;i<len-1;i++)
{
for(int j=i+1;j<len;j++)
{
if(nums[i]==nums[j])
{
return nums[i];
}
}
}
return -1;
该题可以用一个undered_map<int,bool>表来解决。若该元素在map表中不存在,则将其map键值设为true,表示添加进去(没有初始化其默认为false),若为true值,表明该元素已经添加过了,即重复,返回即可;此时只遍历了一次数组,复杂度为O(n),空间复杂度为O(n)。
int findRepeatNumber(vector<int>& nums) {
unordered_map<int,bool>map; //创建一个hash映射表,若nums[i]在该表中存在,则说明重复,不存在,则将其map[nums[i]]设为true 表示添加进去
for(int num:nums)//遍历数组
{
if(map[num])//若其为true表示已经添加过了,该元素重复,返回
{
return num;
}
else
{
map[num]=true;
}
}
return -1;
}
还有一种节约空间复杂度的方法,原地交换,即利用题中条件,长度为n,且数值大小在0~n-1之间,因此,可遍历数组并通过交换操作,使元素的索引与值 一一对应(即 nums[i] = i)。因而,就能通过索引映射对应的值,起到与字典等价的作用。第一次遇到x值,则将其交换至索引x处,第二次遇到x值,则必有nums[x]=x,即x元素重复,返回x即可。时间复杂度也为O(n),因为只需遍历一次,空间复杂度为O(1)。
int findRepeatNumber(vector<int>& nums) {
int n=nums.size();
for(int i=0;i<n;)//注意此处不能设置i++,只能当nums[i]==i时才能i++判断下一元素 或者直接用while
{
if(nums[i]==i)//若索引值等于其元素值,则直接进行下一个位置的比较
{
i++;
continue;
}
if(nums[i]==nums[nums[i]]) //若某元素的值等于该值的索引位置的值,则说明重复,返回即可
{
return nums[i];
}
//不等于,与该元素的值的索引位置的元素交换即可
swap(nums[i],nums[nums[i]]);
}
return -1;
}