2021.11.11
3. 无重复字符的最长子串
第一次代码空间复杂度大:
public class Solution {
public int lengthOfLongestSubstring(String s) {
if(s.length() <= 0)
return 0;
StringBuffer strb = new StringBuffer(s.length());
strb.append(s, 0, 1);
int result = 1;
int length = 1;
for (int i = 1; i < s.length(); i++) {
if(strb.indexOf(s.substring(i,i+1)) != -1){
int index = strb.indexOf(s.substring(i,i+1));
if(result < length)
result = length;
strb = new StringBuffer(strb.substring(index + 1, strb.length()));
}
strb.append(s,i,i+1);
length = strb.length();
}
return result > length ? result : length;
}
}
第二次 滑动窗口+map
public class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
int n = s.length(), result = 0;
int start = 0, end = 0;
for (; end < n; end++) {
char op = s.charAt(end);
if(map.containsKey(op)){
start = Math.max(start, map.get(op));
}
result = Math.max(result, end - start + 1);
map.put(op, end + 1);
}
return result;
}
}
4. 寻找两个正序数组的中位数
第一次,时间复杂度(m+n),空间复杂度(m+n)不符合
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n = nums1.length + nums2.length;
int[]num = new int[n+1];
int i = 0, j = 0, k = 0;
for (; i < n && j < nums1.length && k < nums2.length; i++) {
if(nums1[j] < nums2[k]){
num[i] = nums1[j++];
}else{
num[i] = nums2[k++];
}
}
while(j < nums1.length){
num[i++] = nums1[j++];
}
while(k < nums2.length){
num[i++] = nums2[k++];
}
if(n % 2 == 0){
return (double) (num[n/2 - 1] + num[n/2]) / 2;
}else{
return (double) num[n/2];
}
}
}
第二次:二分查找(太强了,我太菜了)
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int n = nums1.length;
int m = nums2.length;
int left = (n + m + 1) / 2;
int right = (n + m + 2) / 2;
//将偶数和奇数的情况合并,如果是奇数,会求两次同样的 k 。
return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;
}
private int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) {
int len1 = end1 - start1 + 1;
int len2 = end2 - start2 + 1;
//让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1( 牛逼啊 )
if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
if (len1 == 0) return nums2[start2 + k - 1];
if (k == 1) return Math.min(nums1[start1], nums2[start2]);
int i = start1 + Math.min(len1, k / 2) - 1;
int j = start2 + Math.min(len2, k / 2) - 1;
if (nums1[i] > nums2[j]) {
return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
}
else {
return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
}
}
5. 最长回文子串
思想:动态规划
dp[i][j] 表示从 i 到 j 是否为回文子串。
dp[i][j] = (s[i] == s[j]) && dp[i + 1][j - 1], 即判断s[i]和s[j]是否相等,相等判断i+1到j-1是否为回文子串,若是则 i 到 j 也是回文子串。
代码实现
import java.util.*;
public class Solution {
public String longestPalindrome(String s) {
int n = s.length();
boolean[][]dp = new boolean[n][n];
for (int i = 1; i < n; i++) {
dp[i][i] = true;
dp[i][i-1] = true;
}
dp[0][0] = true;
int posx = 0, posy = 0, max = 0;
for (int j = 1; j < n; j++) {
for (int i = 0; i < j ; i++) {
if(dp[i+1][j-1] && s.charAt(i) == s.charAt(j)){
dp[i][j] = true;
if (Math.abs(i-j) + 1 > max){
max = Math.abs(i-j) + 1;
posx = i;
posy = j;
}
}
else dp[i][j] = false;
}
}
return s.substring(posx, posy + 1);
}
public static void main(String[] args) {
Solution s = new Solution();
Scanner in = new Scanner(System.in);
System.out.println(s.longestPalindrome("cbbd"));
}
}
6. Z 字形变换
思路:
public String convert(String s, int numRows) {
if(s.length() <= 2) return s;
if(numRows == 1) return s;
// List<StringBuffer> list = new ArrayList<>();
StringBuffer[] stb = new StringBuffer[numRows];
for (int i = 0; i < numRows; i++) {
stb[i] = new StringBuffer();
}
int i = 0, flag = -1;
for (char op : s.toCharArray()) {
stb[i].append(op);
if(i == 0 || numRows - 1 == i) flag = -flag;
i += flag;
}
StringBuffer res = new StringBuffer();
for (int j = 0; j < numRows; j++) {
res.append(stb[j]);
}
return new String(res);
}