参考思路:
注意点一:牌值为10以内的数组成,且两位数组成只为100以内的数,可用该两位数作为hash方法存储的地址,在数组中存储牌对数量。
注意点二:反转相等,则可自己制定规则,二维数据中,第一维始终小于第二维的数。
注意点三:如果牌对数为n,则能组成的排列数为Cn2
class Solution {
public:
int numEquivDominoPairs(vector<vector<int>>& dominoes) {
if (dominoes.empty())
return 0;
int num = dominoes.size();
vector<int> numbers(100);
int result = 0;
for( int i=0;i<num;i++) //将所有的牌整理成小数在前 大数在后
{
int val;
val = dominoes[i][0] < dominoes[i][1]?dominoes[i][0]*10+dominoes[i][1]:dominoes[i][1]*10+dominoes[i][0];
result+= numbers[val];
numbers[val]++;
}
return result;
}
};
思路:普通思路就不多述说了,hash方法:将该数存在map容器中,将该数作为key值,遇到相同的数则存在value的vector数组中,查找复杂度为O(n),算法复杂度也为O(n)。
class Solution {
public:
/**
*
* @param numbers int整型vector
* @param target int整型
* @return int整型vector
*/
vector<int> twoSum(vector<int>& numbers, int target) {
// write code here
if (numbers.empty())
return {};
int index1,index2;
int flag=0;
// for (int i=0;i<numbers.size();i++)
// {
// if (numbers[i] > target )
// continue;
// index1 = i;
// for (int j=i+1;j<numbers.size();j++)
// {
// if ( numbers[i]+numbers[j] == target )
// {
// index2 = j;
// flag = 1;
// break;
// }
// }
// if (flag == 1)
// break;
// }
//hash方法
map<int, vector<int>> mapvalue;
map<int, vector<int>>::iterator iter1,iter2;
//存入hashtble
for (int i=0;i<numbers.size();i++)
{
iter1 = mapvalue.find(numbers[i]);
if ( iter1 == mapvalue.end()) //未找到该元素
{
vector<int>indexs;
indexs.push_back(i);
mapvalue.insert(pair<int,vector<int>>(numbers[i],indexs));
}
else
iter1->second.push_back(i);
}
for (int i=0;i<numbers.size();i++)
{
if (numbers[i] > target )
continue;
iter1 = mapvalue.find(numbers[i]);
if ( iter1 != mapvalue.end())
{
int next = target - iter1->first;
index1 = iter1->second[0];
iter2 = mapvalue.find(next);
if (iter2 != mapvalue.end() && ((iter1->second[0]!=iter2->second[0]) || (iter1->second[0]==iter2->second[0] && iter1->second.size()>1)) )
{
if (iter2->first == iter1->first)
index2 = iter2->second[1];
else
index2 = iter2->second[0];
flag = 1;
break;
}
}
}
if (index1 < index2)
return {index1+1,index2+1};
else
return {index2+1,index1+1};
}
};
思路:类似的题目均考虑逆序插入(尾插法),不用一一考虑是否需要后移,之后只需要比较大小,选择哪个数进行插入。
class Solution {
public:
void merge(int A[], int m, int B[], int n) {
int index1=m-1,index2=n-1;
int end = m+n-1;
while ( index1>=0 && index2>=0)
{
A[end--] = A[index1]>B[index2]?A[index1--]:B[index2--];
}
while (index1>=0)
A[end--] = A[index1--];
while (index2>=0)
A[end--] = B[index2--];
}
};
其中,while(index1>=0)这段其实可以不写,因为此时index1=end。