public static boolean hasUniqueChar(String string) {
// Total 256 characters in ASCII
if (string.length() > 256) {
return false;
}
boolean[] count = new boolean[256];
for (int i = 0; i < string.length(); i++) {
// If visited before
if (count[(int) string.charAt(i)]) {
return false;
}
// Initialize
count[(int) string.charAt(i)] = true;
}
return true;
}
在ASCII(非Unicode)编码中,共有256个字符。如果string长度超过256,则肯定有重复。
使用一个数组count来表征这个string,数组初始值为false。每个字母对应一个数组里的元素,index是其ASCII码。
该程序将赋值和判断合二为一,先判断再赋值。
如果输入string只含有a到z的字母,则可以用int替代数组。
public static boolean hasUniqueLowerChar(String string) {
// An int is 32 bits. a to z is 26
int count = 0;
// Use 1 bit to represent a character.
for (int i = 0; i < string.length(); i++) {
int val = string.charAt(i) - 'a';
int bit = 1 << val;
if ((count & bit) > 0) {
return false;
}
count |= bit;
}
return true;
}
一个int为32位,而a到z共有26个字母,故可以用1 bit来表示一个字母(如 0000100)。凡是需要一系列标志位的,如果数量少(32 位用int,64位以内用long),可以考虑用bit vector。
使用一个整数count来表征这个string,初始值为0。每个字母对应count里的一位bit,如果有则为1,如果无则为0。
该程序将赋值和判断合二为一,先判断再赋值。
简单的想,只要比较排序后两个string是否equal即可。
public static boolean isPermux(String s, String t) {
if (s.length() != t.length()) {
return false;
}
char[] sArray = s.toCharArray();
char[] tArray = t.toCharArray();
Arrays.sort(sArray);
Arrays.sort(tArray);
return Arrays.equals(sArray, tArray);
}
这里用了Arrays的API函数sort和equals。直接用数组的equals等价于==,故不适用。
public static boolean isPermutation(String s, String t) {
if (s.length() != t.length()) {
return false;
}
int[] count = new int[256];
for (int i = 0; i < s.length(); i++) {
count[s.charAt(i)]++;
}
for (int i = 0; i < t.length(); i++) {
if (--count[t.charAt(i)] < 0) {
return false;
}
}
return true;
}
首先两个string的长度要一致才可能是异构词(“abcd”, "dcab")。
用一个数组count来表示第一个string,数组初始化为0,记录每个字母出现次数。同样假设是ASCII编码。
利用数组count来比较另一个string,只有当两个string的字母计数一致才是变化词。
3. 将空格替换为%20
public static void replaceSpace(char[] string, int length) {
int spaceCount = 0;
for (char i : string) {
if (i == ' ') {
spaceCount++;
}
}
int newLength = length + 2 * spaceCount;
int i = length - 1;
int j = newLength - 1;
while (i >= 0) {
if (string[i] != ' ') {
string[j] = string[i];
} else {
string[j--] = '0';
string[j--] = '2';
string[j] = '%';
}
i--;
j--;
}
}
两次遍历法:第一次从头到尾数空格的数量,确定新string长度;第二次从尾到头,填充新string。
4. 压缩string,将字母计数
例如:aabcccccaaa 压缩为a2b1c5a3,abcdefg 压缩后长度没有减小故仍返回abcdefg。
public static String compressString(String string) {
StringBuffer sb = new StringBuffer();
char last = string.charAt(0);
int count = 1;
for (int i = 1; i < string.length(); i++) {
if (string.charAt(i) == last) {
count++;
} else {
sb.append(last);
sb.append(count);
last = string.charAt(i);
count = 1;
}
}
sb.append(last);
sb.append(count);
if (sb.length() >= string.length()) {
return string;
} else {
return sb.toString();
}
}
注意要把最后的字母append上,count从1计数。
例如:[1,2; 3,4] 旋转为 [3,1; 4,2]
public static void rotateImage(int[][] matrix) {
<span style="white-space:pre"> </span>int n = matrix.length;
for (int row = 0; row < n / 2; row++) {
<span style="white-space:pre"> </span> // n - row - 1 - row + 1 = n - 2*row
<span style="white-space:pre"> </span> for (int col = row; col < n - row - 1; col++) {
<span style="white-space:pre"> </span> int temp = matrix[row][col];
<span style="white-space:pre"> </span>// left to top
<span style="white-space:pre"> </span> matrix[row][col] = matrix[n - 1 - col][row];
<span style="white-space:pre"> </span> // bottom to left
<span style="white-space:pre"> </span>matrix[n - 1 - col][row] = matrix[n - 1 - row][n - 1 - col];
<span style="white-space:pre"> </span> // right to bottom
<span style="white-space:pre"> </span> matrix[n - 1 - row][n - 1 - col] = matrix[col][n - 1 - row];
<span style="white-space:pre"> </span>// top to right
<span style="white-space:pre"> </span> matrix[col][n - 1 - row] = temp;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
}
1. 只需要转一半的行。
2. 以对角线上的元素为基础。for循环次数记得用减法来确定。每下一层,列size减2,故size为n - 2*row。起点为row,则条件为 n - 2*row + row - 1。
3. 画矩阵,判断元素位置的关系。
0,0 | 0,1 | 0,2 | 0,3 |
1,0 | 1,1 | 1,2 | 1,3 |
2,0 | 2,1 | 2,2 | 2,3 |
3,0 | 3,1 | 3,2 | 3,3 |
1,1 = 2,1
2,1 = 2,2
2,2 = 1,2
每一行颜色相同的值相同,颜色不同的和为定值。
矩阵中有0的地方,使其行列均变成0。
public static void setZeroCross(int[][] matrix) {
boolean[] row = new boolean[matrix.length];
boolean[] col = new boolean[matrix[0].length];
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;
col[j] = true;
}
}
}
// Nullify rows
for (int i = 0; i < row.length; i++) {
if (row[i]) {
for (int j = 0; j < matrix[0].length; j++) {
matrix[i][j] = 0;
}
}
}
// Nullify cols
for (int i = 0; i < col.length; i++) {
if (col[i]) {
for (int j = 0; j < matrix.length; j++) {
matrix[j][i] = 0;
}
}
}
}
利用两个标志位数组分别存放行置零标志和列置零标志,来区分哪些是原矩阵的0,哪些是要变成0。首先遍历,找到0位置,置对应的行列标志位。
然后依次置相应的行列为0。
7. 判断是否是旋转string
例如:waterbottle 和 erbottlewat 。由x = wat,y = erbottle 两段组成。xy 和 yx 两种组合都是 xyxy组合的子string。
public static boolean isRotation(String s1, String s2) {
if (s1.length() != s2.length()) {
return false;
}
String s1s1 = s1 + s1;
return isSubstring(s1s1, s2);
}
public static boolean isSubstring(String s, String t) {
if (s.length() < t.length()) {
return false;
}
int sIndex = 0;
int tIndex = 0;
while (sIndex < s.length()) {
if (s.charAt(sIndex) == t.charAt(tIndex)) {
tIndex++;
} else {
tIndex = 0;
}
sIndex++;
if (tIndex == t.length()) {
return true;
}
}
return false;
}
将一个string自己复制组合,判断另一个string是不是这个组合string的子string。