做法一:空间复杂度O(n),时间复杂度O(n).使用哈希存储
cpp
class Solution {
public:
int singleNumber(vector<int>& nums) {
unordered_set<int>mp;
for(auto num:nums)
{
if(mp.find(num)!=mp.end())
{
mp.erase(num);
}
else
{
mp.insert(num);
}
}
return *mp.begin();
}
};
做法二:空间复杂度常数级。异或即可。
cpp
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans=0;
for(int num:nums)ans^=num;
return ans;
}
};
做法一:哈希表维护即可
cpp
class Solution {
public:
int majorityElement(vector<int>& nums) {
unordered_map<int,int> counts;
int majority=0,cnt=0;
for(int num:nums)
{
counts[num]++;
if(counts[num]>cnt)
{
majority=num;
cnt=counts[num];
}
}
return majority;
}
};
做法二:直接返回 sort后数组中间的数字
cpp
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(),nums.end());
return nums[nums.size()/2];
}
};
做法一:单指针,遍历两次即可
cpp
class Solution {
public:
void sortColors(vector<int>& nums) {
int n=nums.size();
int ptr=0;
for(int i=0;i<n;i++)
{
if(nums[i]==0)
{
swap(nums[i],nums[ptr]);
ptr++;
}
}
for(int i=ptr;i<n;i++)
{
if(nums[i]==1)
{
swap(nums[i],nums[ptr]);
ptr++;
}
}
}
};
做法二:双指针,一个指针交换0,一个指针交换1。当交换0的时候,有可能这个位置已经为1了,这样1又被交换走了,而且因为i++,不会再遍历回来,所以要在p0<p1的时候,交换i和p1
cpp
class Solution {
public:
void sortColors(vector<int>& nums) {
int n=nums.size();
int p0=0,p1=0;
for(int i=0;i<n;i++)
{
if(nums[i]==1)
{
swap(nums[i],nums[p1]);
p1++;
}
else
{
if(nums[i]==0)
{
swap(nums[i],nums[p0]);//交换后i的位置可能是1
if(p0<p1)swap(nums[i],nums[p1]);
p0++;
p1++;
}
}
}
}
};
做法三:也是双指针
cpp
class Solution {
public:
void sortColors(vector<int>& nums) {
int n=nums.size();
int p0=0,p2=n-1;
for(int i=0;i<=p2;i++)
{
while(i<=p2&&nums[i]==2)
{
swap(nums[i],nums[p2--]);
}
if(nums[i]==0)
{
swap(nums[i],nums[p0++]);
}
}
}
};
做法:首先从后往前找到第一个a[i]<a[i+1],此时[i+1,n-1]是递减的,可能是这样的 15432,那么此时,我们需要做的就是找到一个比较小数大一点的较大数,并且和较小数交换,然后我们得到25431,[i+1,n-1]还是维持递减性质,之后反转i+1,到n-1.使用reverse函数即可
cpp
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int i=nums.size()-2;
while(i>=0&&nums[i]>=nums[i+1])i--;
if(i>=0)
{
int j=nums.size()-1;
while(j>=0&&nums[i]>=nums[j])j--;
swap(nums[i],nums[j]);
}
reverse(nums.begin()+i+1,nums.end());
}
};
做法一:这道题可以用二分(是的,我也没有想到),假设数组是n+1=5,也就是说数字[1,4]中有重复元素,我们定义cnt[i]为数组中小于等于i元素个数,我们可以发现,当数组中重复元素只有两个的时候例如(1,2,3,3,4),cnt[1]=1,cnt[2]=2,cnt[3]=4,cnt[4]=5,设重复数字为target,[1,target-1]的cnt<=自身,[target,n-1]>自身,所以可以通过二分来寻找,时间复杂度为O(nlogn),当数组中重复元素多于2的情况,假设被替换的数字<target,[i,target-1]-1,[target,n-1]+1,所以对大于小于的性质没有影响
cpp
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int n=nums.size();
int l=1,r=n-1,ans=-1;
while(l<=r)
{
int mid=(l+r)>>1;
int cnt=0;
for(int i=0;i<n;i++)
{
cnt+=nums[i]<=mid;
}
if(cnt<=mid)
{
l=mid+1;
}
else
{
r=mid-1;
ans=mid;
}
}
return ans;
}
};
做法二:快慢指针。这个有点难理解,之后再来
cpp
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int slow=0,fast=0;
do
{
slow=nums[slow];
fast=nums[nums[fast]];
}while(slow!=fast);
slow=0;
while(slow!=fast)
{
slow=nums[slow];
fast=nums[fast];
}
return slow;
}
};
做法三:二进制
cpp
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int n=nums.size(),ans=0;
int bit_max=31;
while(!((n-1)>>bit_max))bit_max-=1;
for(int bit=0;bit<=bit_max;bit++)
{
int x=0,y=0;
for(int i=0;i<n;i++)
{
if(nums[i]&(1<<bit))
{
x+=1;
}
if(i&(1<<bit))y+=1;
}
if(x>y)ans|=1<<bit;
}
return ans;
}
};
ending!!!!但是还是需要复习,很多时候不够专心致志去解决问题,一定要细致的再看一次,加油吧。fighting~