首先应该问清楚使用ASCII还是Unicode字符串。
假设为前者,如果字符串的长度大于256,则返回0,第一种思路就是构建一个布尔型的数组,
索引值i表示该字符串是否含有字母表的第i个字符。若字符第二次出现,则为假。
bool isUniqueChar(string str) { if(str.length() > 256) return false; bool *char_set = new bool[256]; for(int i = 0;i<str.length();i++) { int val = static_cast<int>(str[i]); if(char_set[val]) return false; char_set[val] = true; } return true; }
不应该忽略的是:不分配额外空间,直接就地反转,另外,还要注意NULL字符。 void reverse(char *str) { char * end = str; char temp; if(str) { while(*end) end++; --end;//最后一个是NULL因此要回退一个字符。 while(str < end) { temp = *str; *str = *end; *end = temp; } } }
首先应该确认的是变位词是否区分大小写,还有空格是否考虑在内。
当然,如果两个字符串的长度不同,一定是不同的。
第一种方法我们考虑,排序字符串。在某种程度上,这个算法不算是最优,不过换个角度看,
这个算法或许更可取,因为它:清晰、简单、易懂。从实践的角度来看,这可能是解决这个问题的上佳之选。
不过,要是效率当头,我们可以换种做法。
方法2:检查两个字符串的各字符数是否相同。
bool permutation(string s,string t) { if(s.length != t.length()) return false; int *letters = new [256]; for(int i = 0;i<256;i++) letters[i] = 0; for(int i = 0;i<s.length();i++) { int pos = (int)s[i]; letters[pos]++; } for(int i = 0;i<t.length();i++) { int pos = (int)t[i]; if(--letters[pos] < 0) return false; } return true; }
void replaceSpace(char str[],int length) { int spaceCount = 0,newLength,i; for(i = 0;i<length;i++) { if(str[i] == ' ') spaceCount++; } newLength = length + spaceCount*2; str[newLength] = '\0'; for(i = newLength - 1;i>=0;i--) { if(str[i] == ' ') { str[newLength - 1] = '0'; str[newLength - 2] = '2'; str[newLength - 3] = '%'; newLength -= 3; } else { str[newLength] = str[i]; newLength--; } } }
//针对上述问题,我们先回给出下面的过程,当然,则个过程没有比较压缩后的字符串与先前字符串的长度问题。 string compressBad(string str) { string mystr = ""; char last = str[0]; int count = 1; for(int i = 1;i<str.length();i++) { if(str[i] == last) count++; else { stringstream ss; ss<<count; mystr += last + ss.str(); last = str[i]; count = 1; } } stringstream s; s<<count; return mystr + last + s.str(); }
基于效率的原因,我们修改如下:
string compressAlternate(string str) { int size = countCompression(str); if(size>=str.length()) return str; char *array = new char[size]; int index = 0; char last = str[0]; int count = 1; fot(int i = 1;i<str.length();i++) { if(last == str[i]) count++; else { index = setChar(array,last,index,count); last = str[i]; count = 1; } } index = setChar(array,last,index,count); return array; } int setChar(char *array,char c,int index,int count) { array[index] = c; index++; ...//复制到新的位置 return index; } int countCompression(string str) { if(str == null || str.isEmpty()) return 0; int size = 0; int count = 1; for(int i = 1;i < str.length();i++) { if(str[i] == last) count++; else { last = str[i]; size = 1 + count.Str.length();//这一行是伪码,方法见上 count = 1; } } size = ...//同上 return size; }
void rotate(int **matrix,int n) { for(int layer = 0;layer<n/2;layer++) { int first = layer; int last = n - 1 - layer; for(int i = first;i<last;i++) { int offset = i - first; int top = matrix[layer][i]; matrix[layer][i] = matrix[last - offset][first]; matrix[last - offset][first] = matrix[last][last - offset]; matrix[last][last - offset] = matrix[i][last]; matrix[i][last] = top; } } }
首先应该清楚的就是不能在第一次遍历矩阵的时候就把行列清零,因为这样会破坏原矩阵的信息,最终导致矩阵全都是零。
因此应该有两次遍历,第一次用两个数组记录零所在的行和所在的列,如果[i][j]是零元素,那么就让row[i]和column[j]都为true。经过一次遍历之后,就能够标识可清零的行和列。如果[2][4],[2][6]为0,只要在row[2]标记为true即可,不需要标识两次,否则会存在多余的二次赋值。
void setZeros(int **matrix) { bool *row = new bool[matrix.length]; bool *column = new bool[matrix[0].length]; //记录0元素的位置 for(int i = 0;i < matrix.length;i++) { for(int j = 0;j < matrix[0].length;j++) { if(matrix[i][j] == 0) { row[i] = true; column[j] = true; } } } for(int i = 0;i<matrix.length;i++) { for(int j = 0;j<matrix[0].length;j++) { if(column[j] || row[i]) matrix[i][j] = 0; } } }
针对这个问题,我们首先应该抽象出来旋转的概念,所谓旋转就是从字符串的中间任意一个位置 切一刀,把切口前面的部分拿到字符串的末尾即可,也就是xy组成元字符串,切口在xy之间,旋转之后 变成yx。加上题意给出的isSubstring我们可以猜测是通过判断子串的方式来判断是否经过旋转而成。 yx一定是xyxy的子串,因此如果是旋转而成的话,上述表明一定成立。
bool isRotation(string s1,string s2) { int len = s1.length(); if(len == s2.length() && len > 0) return isSubstring(s1+s1,s2); return false; }