目录
1.数组中只出现一次的两个数字
vector<int> FindNumsAppearOnce(vector<int>& array) {
// write code here
map<int, int> m; //定义一个map遍历
for (auto e : array)
m[e]++; //把每个数字出现的次数统计一下
vector<int> ans; //存放最后唯一出现的两个元素
for (auto e : m)
if (e.second == 1) ans.push_back(e.first);
if (ans[0] > ans[1]) //题目要求返回必须升序
swap(ans[0], ans[1]);
return ans;
}
2.缺失的第一个正整数
int minNumberDisappeared(vector<int>& nums) {
// write code here
int tmp=1;
sort(nums.begin(),nums.end());
for( auto e:nums)
{
if(e<=0) continue;
if(e==tmp) tmp++;
else return tmp;
}
return tmp;
}
3.三数之和
vector<vector<int> > threeSum(vector<int>& num) {
sort(num.begin(), num.end()); //首先排序
vector<vector<int>>ans; //ans记录答案三元组数组
map<int, vector<int> > m;//记录找到的两个数,用这两个数去寻找第三个数
map<pair<int, int>, int> mp; //为了去重
for (int i = 0; i < num.size(); i++)
{
m[num[i]].push_back(i); //首先把num记录下来,然后把对应的下标也记录
}
for (int i = 0; i < num.size(); i++)
{
for (int j = i + 1; j < num.size(); j++)
{
int sum = num[i] + num[j]; //sum为前两个数之和
if (m.count(-sum)) //-sum是第三个数,如果这个数存在
{
vector<int> tmp; //临时三元组,需要判断他是不是符合要求
tmp.push_back(num[i]);
tmp.push_back(num[j]);
tmp.push_back(-sum);
int a = (num[i] == -sum) + (num[j] == -sum);
//a记录了第三个数和前两个数中的几个相等,a=0说明第三个数和前两个都不等,a=1和其中一个等,a=2三数相等
if (m[-sum].size() <= a) continue; //如果第三个数的下标的数目之和<=a,小于说明数组里没有第三个数
//比如a=1,假设第三个数=第一个数=10,m[-sum].size()就是记录10的个数,若m[-sum].size()<1说明数组里连10这个数都没有
//m[-sum].size()=1,说明数组里10这个数只有一个,就是第一个数,所以第三个数还是不存在
sort(tmp.begin(), tmp.end()); //此时第三个数存在,给tmp排成非降序
if (mp.count({ tmp[0],tmp[1] }) != 0) continue; //如果mp里面存在这样的三元组,说明重复
ans.push_back(tmp); //此时满足一个三元组的所有要求,加入到答案里
mp[{tmp[0], tmp[1]}] = tmp[2]; //用第三个数标记这个三元组
}
}
}
return ans;
}
4.没有重复数字的全排列
这个题太容易把自己绕进去了
首先肯定是回溯的思想,如果只有一个数字全排列,直接用一个临时vector v压入这个数字,然后ans把v压入,然后把这个元素从v中pop
但是如果更复杂,不止一个数字,所以思路就是:
先把第一个数字压入,然后用一个临时vector t,储存除了v中的数字
然后开始把临时变量当做v取数字的范围
vector<vector<int> > permute(vector<int>& num) {
vector<vector<int>> ans;
vector<int> v;
recursion(num, v, ans);
return ans;
}
void recursion(vector<int> num, vector<int>& v, vector<vector<int>>& ans)
{
if (num.size() == 1) //回溯
{
v.push_back(num[0]);
ans.push_back(v);
v.pop_back();
return;
}
for (auto e : num)
{
v.push_back(e);
vector<int> t;
for (auto i : num)
if (i != e) t.push_back(i);
recursion(t, v, ans);
v.pop_back();
}
}
5.有重复项数字的全排列
重复项那我们思路就和上一个题 稍微不一样,之前是不能重复,所以i和e不能相等
但是这次只要下标不一样就可以,但是会有重复,所以直接用set去重,然后转成vector
vector<vector<int> > permuteUnique(vector<int> &num) {
set<vector<int>> ans;
vector<int> v;
recursion(num, v, ans);
return vector<vector<int>>(ans.begin(),ans.end());
}
void recursion(vector<int> num, vector<int>& v, set<vector<int>>& ans)
{
if (num.size() == 1) //回溯
{
v.push_back(num[0]);
ans.insert(v);
v.pop_back();
return;
}
for (int i=0;i<num.size();i++)
{
v.push_back(num[i]);
vector<int> t;
for (int j=0;j<num.size();j++)
if (i != j) t.push_back(num[j]);
recursion(t, v, ans);
v.pop_back();
}
}