//无重复字符的最长子串
//主要思路滑动窗口 遍历字符串不重复的情况时最长子串长度加一当遍历到 重复元素时 从重复元素往后开始计算 并
//与目前最大长度子串比较大小 取最大值
public static int lengthOfLongestSubstring(String s) {
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
int lef = 0;
for (int i = 0; i < s.length(); i++) {
if (map.containsKey(s.charAt(i))) {
lef = Math.max(lef, map.get(s.charAt(i)) + 1);
}
map.put(s.charAt(i), i);
max = Math.max(max, i - lef + 1);
}
return max;
// if (s.length()==0) return 0;
// HashMap<Character, Integer> map = new HashMap<Character, Integer>();
// int max = 0;
// int left = 0;
// for(int i = 0; i < s.length(); i ++){
// if(map.containsKey(s.charAt(i))){
// left = Math.max(left,map.get(s.charAt(i)) + 1);
// }
// map.put(s.charAt(i),i);
// max = Math.max(max,i-left+1);
// }
// return max;
}
最长回文字符串
找出最长公共子串
public static String longestPalindrome(String s) {
if (s.equals(""))
return "";
String origin = s;
String reverse = new StringBuffer(s).reverse().toString();
int length = s.length();
int[][] arr = new int[length][length];
int maxLen = 0;
int maxEnd = 0;
for (int i = 0; i < length; i++)
for (int j = 0; j < length; j++) {
if (origin.charAt(i) == reverse.charAt(j)) {
if (i == 0 || j == 0) {
arr[i][j] = 1;
} else {
arr[i][j] = arr[i - 1][j - 1] + 1;
}
}
if (arr[i][j] > maxLen) {
int beforeRev = length - 1 - j;
if (beforeRev + arr[i][j] - 1 == i) {
maxLen = arr[i][j];//记录公共子串的最大长度
maxEnd = i;//记录公共子串最大长度子串的最后一个坐标
}
}
}
return s.substring(maxEnd - maxLen + 1, maxEnd + 1);
}
Z字形变换
我一开始的思路是利用二维数组计算下标这样太麻烦
官方的思路非常巧妙 感觉自己真的是个智障一样 为什么就想不到 代码如下:
public static String convert(String s, int numRows) {
if (numRows == 1) return s;
List<StringBuilder> rows = new ArrayList<>();
for (int i = 0; i < Math.min(numRows, s.length()); i++)
rows.add(new StringBuilder());
int curRow = 0;
boolean goingDown = false;
for (char c : s.toCharArray()) {
rows.get(curRow).append(c);
if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
curRow += goingDown ? 1 : -1;
}
StringBuilder ret = new StringBuilder();
for (StringBuilder row : rows) ret.append(row);
return ret.toString();
}
三数之和
我自己的代码
public static List<List<Integer>> threeSum(int[] nums) {
Long begin = System.currentTimeMillis();
List<Integer> numbers = new ArrayList<Integer>();
List<Integer> res = null;
List<List<Integer>> result = new ArrayList<List<Integer>>();
int sum = 0;
for (int i = 0; i < nums.length; i++) {
numbers.add(nums[i]);
}
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length; j++) {
if (i == j) {
continue;
}
sum = (nums[i] + nums[j]) * -1;
numbers.remove((Object) nums[i]);
numbers.remove((Object) nums[j]);
if (numbers.contains(sum)) {
res = new ArrayList<Integer>();
res.add(nums[i]);
res.add(nums[j]);
res.add(sum);
Collections.sort(res);
if (!result.contains(res)) {
result.add(res);
}
}
numbers.add(nums[i]);
numbers.add(nums[j]);
}
}
Long end = System.currentTimeMillis();
System.out.println(end - begin);
return result;
}
运行之后再LeetCode上面超时了 一开始卡在了去重的阶段 后利用Collections.sort方法去重,但是随之而来的就是时间复杂度也增加了 因为sort方法里面 还有一层for循环。看完题解 记录一下优化后的结果,先将数组进行排序,利用双指针法。固定一个 指针 其他两个分别从两边相向而行记录满足条件的结果。
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> ans = new ArrayList();
int len = nums.length;
if(nums == null || len < 3) return ans;
Arrays.sort(nums); // 排序
for (int i = 0; i < len ; i++) {
if(nums[i] > 0) break; // 如果当前数字大于0,则三数之和一定大于0,所以结束循环
if(i > 0 && nums[i] == nums[i-1]) continue; // 去重
int L = i+1;
int R = len-1;
while(L < R){
int sum = nums[i] + nums[L] + nums[R];
if(sum == 0){
ans.add(Arrays.asList(nums[i],nums[L],nums[R]));
while (L<R && nums[L] == nums[L+1]) L++; // 去重
while (L<R && nums[R] == nums[R-1]) R--; // 去重
L++;
R--;
}
else if (sum < 0) L++;
else if (sum > 0) R--;
}
}
return ans;
}
电话号码的字母组合 用到回溯 这道题 感觉上是遍历树结构的操作 要是数据结构树那里学的比较好的话可能这里应该不是什么很困难的问题
Map<String, String> phone = new HashMap<String, String>() {{
put("2", "abc");
put("3", "def");
put("4", "ghi");
put("5", "jkl");
put("6", "mno");
put("7", "pqrs");
put("8", "tuv");
put("9", "wxyz");
}};
List<String> output = new ArrayList<String>();
public void backtrack(String combination, String next_digits) {
if (next_digits.length() == 0) {
output.add(combination);
}else{
String digit = next_digits.substring(0, 1);
String letters = phone.get(digit);
for (int i = 0; i < letters.length(); i++) {
String letter = phone.get(digit).substring(i, i + 1);
backtrack(combination + letter, next_digits.substring(1));
}
}
}
public List<String> letterCombinations(String digits) {
if (digits.length() != 0)
backtrack("", digits);
return output;
}