No buffer interchange
函数内不使用任何临时变量,直接交换两个数的值。
给定一个int数组AB,其第零个元素和第一个元素为待交换的值,请返回交换后的数组。
class Exchange {
public:
vector<int> exchangeAB(vector<int> AB) {
AB[0] = AB[1] - AB[0];
AB[1] = AB[1] - AB[0];
AB[0] = AB[0] + AB[1];
return AB;
}
};
Group angrams
对一个字符串数组进行排序,将所有变位词合并,保留其字典序最小的一个串。这里的变位词指变换其字母顺序所构成的新的词或短语。例如”triangle”和”integral”就是变位词。
给定一个string的数组str和数组大小int n,请返回排序合并后的数组。保证字符串串长小于等于20,数组大小小于等于300。
在这道题目中有两个需求,一个是去重保留顺序更前面的字符串,第二个是对不重复的字符串进行排序。
代码实现:
class SortString {
public:
__inline void calculateHash(vector<int>& hash, string str) {
for(int i = 0, sz = str.length(); i < sz; i++)
hash[str[i]-'a']++;
}
__inline void mergeSort(vector<string>& res, vector<string>& helper, int low, int high) {
if(low < high) {
int mid = (low + high) >> 1;
mergeSort(res, helper, low, mid);
mergeSort(res, helper, mid+1, high);
mergeArray(res, helper, low, mid, high);
}
}
void mergeArray(vector<string>& arr1, vector<string>& arr2, int low, int mid, int high) {
for(int i = low; i <= high; i++) arr2[i] = arr1[i];
int helperLeft = low, helperRight = mid+1, cur = low;
while(helperLeft <= mid && helperRight <= high) {
if(arr2[helperLeft] <= arr2[helperRight]) {
arr1[cur] = arr2[helperLeft];
helperLeft++;
}
else {
arr1[cur] = arr2[helperRight];
helperRight++;
}
cur++;
}
int rem = mid - helperLeft;
for(int i = 0; i <= rem; i++) arr1[cur+i] = arr2[helperLeft + i];
}
vector<string> sortStrings(vector<string> str, int n) {
vector<string> res;
vector<vector<int>> hash_table(300, vector<int>(26, 0));
if(!n) return res;
res.push_back(str[0]);
calculateHash(hash_table[0], str[0]);
for(int i = 1; i < n; i++) {
vector<int> hash_cur(26, 0);
calculateHash(hash_cur, str[i]);
for(int j = 0, cur_size = res.size(); j < cur_size; j++) {
if(hash_cur == hash_table[j]) {
if(str[i] < res[j]) res[j] = str[i];
}
else if(j == cur_size - 1){
res.push_back(str[i]);
hash_table[cur_size] = hash_cur;
}
}
}
vector<string> helper(res.size(), "");
mergeSort(res, helper, 0, res.size() - 1);
return res;
}
};
Sparse Search
一个稀疏矩阵需要进行二分查找,需要注意字符串为空的情况。
有一个排过序的字符串数组,但是其中有插入了一些空字符串,请设计一个算法,找出给定字符串的位置。算法的查找部分的复杂度应该为log级别。
给定一个string数组str,同时给定数组大小n和需要查找的string x,请返回该串的位置(位置从零开始)。
代码实现:
class Finder {
public:
int findString(vector<string> str, int n, string x) {
int low = 0, high = n - 1;
while(low <= high) {
while(str[low].empty()) low++;
while(str[high].empty()) high--;
int mid = (low + high) >> 1;
int leftBnd = mid, rightBnd = mid;
while(leftBnd >= low && str[leftBnd].empty()) leftBnd--;
while(rightBnd <= high && str[rightBnd].empty()) rightBnd++;
if(str[leftBnd] == x || str[rightBnd] == x) return leftBnd;
else if(str[rightBnd] < x) low = rightBnd + 1;
else if(str[leftBnd] > x) high = leftBnd - 1;
}
return -1;
}
};
Search in Rotated Array
有一个排过序的数组,包含n个整数,但是这个数组向左进行了一定长度的移位,例如,原数组为[1,2,3,4,5,6],向左移位5个位置即变成了[6,1,2,3,4,5],现在对于移位后的数组,需要查找某个元素的位置。请设计一个复杂度为log级别的算法完成这个任务。
给定一个int数组A,为移位后的数组,同时给定数组大小n和需要查找的元素的值x,请返回x的位置(位置从零开始)。保证数组中元素互异。
就是将一个数组进行旋转,然后找到需要找到的数字的索引,然后返回。
这里需要注意的就是索引的使用会有些复杂。
这里我实现的思路是先找到最小元素的索引,在这个基础上,在进行二分查找。
代码实现:
class Finder {
public:
int findElement(vector<int> A, int n, int x) {
int low = 0, high = n - 1, mid = 0;
while (low <= high) {
mid = (low + high) >> 1;
if (A[mid] > A[low]) low = mid;
else if (A[mid] < A[high]) high = mid;
else {
if (A[high] < A[low]) { mid = high; break; }
else { mid = low; break; }
}
}
low = mid, high = mid ? mid - 1 : n - 1;
int abt_low = 0, abt_high = n - 1;
while (abt_low <= abt_high) {
int abt_mid = (abt_low + abt_high) >> 1;
mid = (abt_mid + low) % n;
if (A[mid] > x) abt_high = abt_mid - 1;
else if (A[mid] < x) abt_low = abt_mid + 1;
else return mid;
if (A[(abt_low + low) % n] == x) return (abt_low + low) % n;
if (A[(abt_high + low) % n] == x) return (abt_high + low) % n;
}
return -1;
}
};
word frequency
请设计一个高效的方法,找出任意指定单词在一篇文章中的出现频数。
给定一个string数组article和数组大小n及一个待统计单词word.
代码实现:
class Frequency {
public:
__inline bool isEqual(string a, string b) {
int lena = a.size(), lenb = b.size();
if(lena != lenb) return false;
for(int i = 0; i < lena; i++) if(a[i] ^ b[i]) return false;
return true;
}
int getFrequency(vector<string> article, int n, string word) {
int res = 0;
for(int i = 0; i < n; i++) {
res += isEqual(word, article[i]);
}
return res;
}
};
no if max implementation
请编写一个方法,找出两个数字中最大的那个。条件是不得使用if-else等比较和判断运算符。
给定两个int a和b,请返回较大的一个数。若两数相同则返回任意一个。
这道题目里,不能使用if else这样的结构,那么就需要进行一些逻辑判断,使用逻辑运算来代替if else的结构。
代码实现:
class Max {
public:
int getMax(int a, int b) {
int bs = ((a - b) >> 31) & 1;
int as = 1 - bs;
for(int i = 1; i < 32; i++) {
bs = bs | (bs << i);
as = as | (as << i);
}
return (bs & b) | (as & a);
}
};
chess board
对于一个给定的井字棋棋盘,请设计一个高效算法判断当前玩家是否获胜。
给定一个二维数组board,代表当前棋盘,其中元素为1的代表是当前玩家的棋子,为0表示没有棋子,为-1代表是对方玩家的棋子。
判断一个棋盘中当前玩家是否赢了。
既然这道题目的棋盘大小是固定的,那么就可以直接判断。
代码实现:
class Board {
public:
bool checkWon(vector<vector<int> > board) {
for(int row = 0; row < 3; row++) {
for(int col = 0; col < 3; col++) {
if(board[row][col] == 1) {
if(col == 0) {
// 1
if(board[row][1] == 1 && board[row][2] == 1) return true;
// 2
if(row == 0) {
if(board[1][1] == 1 && board[2][2] == 1) return true;
}
}
// 3
if(row == 0) {
if(board[1][col] == 1 && board[2][col] == 1) return true;
// 4
if(col == 2) {
if(board[1][1] == 1 && board[2][0] == 1) return true;
}
}
}
}
}
return false;
}
};
guess score
我们现在有四个槽,每个槽放一个球,颜色可能是红色(R)、黄色(Y)、绿色(G)或蓝色(B)。例如,可能的情况为RGGB(槽1为红色,槽2、3为绿色,槽4为蓝色),作为玩家,你需要试图猜出颜色的组合。比如,你可能猜YRGB。要是你猜对了某个槽的颜色,则算一次“猜中”。要是只是猜对了颜色但槽位猜错了,则算一次“伪猜中”。注意,“猜中”不能算入“伪猜中”。
给定两个string A和guess。分别表示颜色组合,和一个猜测。请返回一个int数组,第一个元素为猜中的次数,第二个元素为伪猜中的次数。
这道题目比较简单,其实只需要把字符创中相等的部分进行计算得到第一个返回的数据。然后第二个返回的数据就排除第一次比较相等的数据,然后使用一个哈希表记录即可得到正确的结果。
class Result {
public:
vector<int> calcResult(string A, string B) {
int hash[4] = {0}; // 1, 2, 3, 4
int rgb[4] = {0};
vector<int> res(2, 0);
for(int i = 0; i < 4; i++) {
if(A[i] ^ B[i]) hash[i] = INT_MAX;
else res[0]++;
}
for(int i = 0; i < 4; i++) {
if(hash[i] == INT_MAX) {
switch(A[i]) {
case 'R': {
if(rgb[0] < 0) res[1]++; rgb[0]++;
break;
}
case 'G': {
if(rgb[1] < 0) res[1]++; rgb[1]++;
break;
}
case 'Y': {
if(rgb[2] < 0) res[1]++; rgb[2]++;
break;
}
default: {
if(rgb[3] < 0) res[1]++; rgb[3]++;
}
}
switch(B[i]) {
case 'R': {
if(rgb[0] > 0) res[1]++; rgb[0]--; break;
}
case 'G': {
if(rgb[1] > 0) res[1]++; rgb[1]--;
break;
}
case 'Y': {
if(rgb[2] > 0) res[1]++; rgb[2]--;
break;
}
default: {
if(rgb[3] > 0) res[1]++; rgb[3]--;
}
}
}
}
return res;
}
};