4. 寻找两个正序数组的中位数
思路:暴力解法,merge两个数组并找中位数。实际我们可以省去merge过程,通过双指针模拟merge找到中位数。因为两个数组都是正序数组,所以从头开始遍历两个数组,将小的那一个去除,同时后移指针并减小计数。直至找到中间的数字。单数长度数组的中位数索引是length / 2,而双数长度数组的中位数索引是length / 2 - 1,与length / 2的两个数字的平均值。
代码:
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
if (nums1.length == 0 && nums2.length == 0) {
return 0;
}
int i1 = 0, i2 = 0, index = (nums1.length + nums2.length) / 2;
boolean isEven = (nums1.length + nums2.length) % 2 == 0;
double result = 0;
while (index >= 0) {
int temp;
if (i1 >= nums1.length) {
temp = nums2[i2];
i2 ++;
index --;
} else if (i2 >= nums2.length) {
temp = nums1[i1];
i1 ++;
index --;
} else {
if (nums1[i1] > nums2[i2]) {
temp = nums2[i2];
i2 ++;
index --;
} else {
temp = nums1[i1];
i1 ++;
index --;
}
}
if ((isEven && index == 0) || index == -1) {
result += temp;
}
}
return isEven ? result / 2 : result;
}
时间复杂度:O(N)
空间复杂度:O(1)
5. 最长回文子串
思路:回文字符串都有回文中心,从头遍历字符串,以每一个位置(长度为奇数)以及每一个间隔(长度为偶数)作为回文中心,向两边延伸,得到可能的回文子串,记录下最长的。
代码:
public String longestPalindrome(String s) {
if (s == null || s.length() <= 0) {
return "";
}
int start = 0, end = 0;
for (int i = 0 ; i < s.length(); i++) {
int len1 = expandFromCenter(s, i, i);
int len2 = expandFromCenter(s, i, i+1);
int len = Math.max(len1, len2);
if (len > end - start + 1) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(start, end + 1);
}
private int expandFromCenter(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left --;
right ++;
}
return right - left - 1;
}
时间复杂度:O(N2)
空间复杂度:O(1)
6. Z字型变换
思路:找规律,发现每个Z的间隔为 (n - 1) * 2,记为space。每一行中两个数的间隔都是有规律的。除了第一行和最后一行外,每个Z都包含两个间隔。遍历每行,取i作为行号,左边的间隔为space - 2 * i,右边的间隔为 2 * i。同时发现这个间隔对第一行和最后一行也适用,不过要注意第一行的右边间隔为0,而最后一行的左边间隔为0。找到了规律后,我们开始逐行读取。使用StringBuilder / char[] 作为结果缓冲区,遍历每行。每行的一个字符的下标为i,然后左右间隔交替推进,若间隔不为0,则将指针更新到推进后的位置,同时将字符放入缓冲区。最后遍历完成后,依照缓冲区内容返回结果。
代码:
public String convert(String s, int numRows) {
if (s == null || s.length() <= 0) {
return "";
}
if (numRows == 1 || numRows > s.length()) {
return s;
}
StringBuilder sb = new StringBuilder();
int space = (numRows - 1) * 2;
for (int i = 0; i < numRows; i++) {
int space1 = space - 2 * i, space2 = space - space1;
int j = i;
sb.append(s.charAt(j));
while (j < s.length()) {
if (space1 != 0) {
j += space1;
if (j < s.length()) {
sb.append(s.charAt(j));
}
}
if (space2 != 0) {
j += space2;
if (j < s.length()) {
sb.append(s.charAt(j));
}
}
}
}
return sb.toString();
}
时间复杂度:O(N)
空间复杂度:O(1)