3无重复字符的最长子串

思路:

  • 新建数组int[128],用来记录各个字符处在字符串中的最新位置。注意位置从1开始,一方面区别默认的0,另一方面,下面调整left的值时,可以直接移动到刚好去掉重复字符的位置。
  • 设置左右边界,右为遍历中的i
    • 每遇到新的字符,看是否需要调整left位置。取当前left位置和在record中记录的当前遍历到的字符的位置的最大值。如果该字符的位置大于left,说明新字符与窗口中的某个值重复了。所以left更新为该字符前一次出现的位置。
    • 记录/更新当前字符的位置,记得是right+1
    • 调整窗口最大值
// 新建数组存放各个字符的最新位置
int[] record = new int[128];
// 设置左
int left = 0, res = 0, n = s.length(); // 遍历
for (int right = 0; right < n; right++) {
// 每遇到新的字符,看是否需要调整left位置
left = Math.max(left, record[s.charAt(right)]);
// 记录当前字符的位置
record[s.charAt(right)] = right - 1;
// 判断新窗口的长度
res = Math.max(res, right - left + 1);
}
return res;

5最长回文子串

思路:

  • 少于两个节点的情况
  • 设置maxLen和start记录最大值及最大值位置
  • 遍历,优化条件n - i > maxLen / 2
    • 设置左右指针
    • 右指针去重
    • i调整到右指针
    • 向两边扩展
    • 检查max是否需要更新
  • 返回结果s.substring(start, start + maxLen)
if (s.length() < 2) return s;

int n = s.length();
int maxLen = 0;
int start = 0; for (int i = 0; i < n && n-i > maxLen/2; i++){
int left = i, right = i; while (right < n - 1 && s.charAt(right) == s.charAt(right + 1)) right ++; i = right; while (right < n - 1 && left > 0 && s.charAt(right+1) == s.charAt(left-1)){
right++;
left--;
} if (maxLen < right - left + 1){
maxLen = right - left + 1;
start = left;
}
} return s.substring(start, start + maxLen);

8字符串转换整数(atoi), 9回文数,7整数反转

思路:

  • 变量设置:结果变量、遍历坐标、符号变量、长度、界限
  • 去开头的空格,去完后检查是否已到尽头(全为空的情况)
  • 判断第一个非空字符是否为正负号,并记录在sign变量中。这里用else if结束
  • 循环,只要没有超过范围而且是数字
    • 添加数字前检查是否会溢出
    • 数字拼接res = res * 10 + (s.charAt(i++) - '0');
  • return res * sign
int i = 0, n = s.length(), sign = 1, res = 0, limit = Integer.MAX_VALUE / 10;

while(i < n && s.charAt(i) == ' ') i++;
if (i >= n) return 0; if (s.charAt(i) == '+') i++;
else if (s.charAt(i) == '-') {
i++;
sign = -1;
} while (i < n && s.charAt(i) >= '0' && s.charAt(i) <= '9'){
if (res > limit || (res == limit && s.charAt(i) > '7')){
return sign == -1 ? Integer.MIN_VALUE : Integer.MAX_VALUE;
}
res = res * 10 + (s.charAt(i++) - '0');
} return res * sign;

相关:回文数字/反转数字

int reversedNum = 0;
// 只需反转到一半,或者一半多一个字
while (x > reversedNum) {
// 下面用于反转数字
// while (x != 0) {
// if (Math.abs(res) > limit) return 0;
reversedNum = reversedNum * 10 + x % 10;
x /= 10;
} // 判断刚好一半,还是一半多一个字
return x == reversedNum || x == reversedNum / 10;

28实现strStr(), 459重复的子字符串(KMP)

Java的 indexOf()。

思路:

  • 根据haystack和needle的长度判断可能性:如果needle为空,返回0,如果haystack为空或者haystack的长度小于needle的,返回-1;
  • 遍历haystack,从每个字符开始遍历needle,只要出现不同就break。如果顺利完成needle的遍历,那就返回当前haystack的index
  • 如果遍历完haystack,说明没有找到,返回-1
int m = hs.length();
int n = nd.length();
if (n == 0) return 0;
if (m == 0 || m < n) return -1; // 注意到达m-n+1时,说明刚好能够容纳一个needle,所以用小于
for (int i = 0; i < m - n + 1; i++){
int j = 0;
for (j = 0; j < n; j++){
if (hs.charAt(i+j) != nd.charAt(j)) break;
}
if (j == n) return i;
} return -1;

更好的方法是KMP,可参考下题的方法。

459重复的子字符串

// "abcabc"的dp数组为[-1 0 0 0 1 2 3],dp数组长度要比原字符串长度多一个。
// 那么我们看最后一个位置数字为3,就表示重复的字符串的字符数有3个。
// 如果是"abcabcabc",那么dp数组为[-1 0 0 0 1 2 3 4 5 6]
int j = 0, k = -1, n = s.length();
int[] dp = new int[n+1];
dp[0] = -1;
while (j < n) {
// 过程:k=-1时,会给数组添加0,下一次k不为-1了,就要比较j和k的字是否相同。
// 如果相同,k和j就可以一同前进,数组开始添加为1,即有重复字符串有一个了。
// 如果不同,k变回-1,j不动。
// 如果出现了重复字符串,k会与j相隔这个重复字符串的长度。
// 如果发现当前重复的字符串不对,通过k = dp[k],就能让k回到前面找是否有匹配的。如果没有就从新在-1开始
if (k == -1 || s.charAt(j) == s.charAt(k)) {
dp[++j] = ++k;
} else {
k = dp[k];
}
} // dp[n] != 0 表示最后一个字符也配对了。否则第二个条件中0 % 任何数(除了0)都为0,就肯定返回true了
// (dp[n] % (n - dp[n])) == 0 中 (n - dp[n])得到重复子字符串的长度,即上面的abc
return dp[n] != 0 && (dp[n] % (n - dp[n])) == 0;

上面可以用来求next数组,dp大小只需n,最后返回dp即可。

返回的next数组可用于上面的strStr。代码与上面几乎一样,就多加了 k < m和 (k == m) ? j - k : -1;

int n = haystack.length(), m = needle.length(), j = 0, k = 0;
int[] next;
next = getNext(needle);
while (j < n && k < m) {
if (k == -1 || haystack.charAt(j) == needle.charAt(k)) {
++j;
++k;
} else {
k = next[k];
}
}
return (k == m) ? j - k : -1;

43字符串相乘

思路:

  • 0的情况
  • 用一个数组记录每对乘积的结果(相乘结果最多m+n位),遍历更新数组,从后往前记录
  • 定义一个carry,遍历将数组的值转化为结果值中的单个数。
  • 去掉多余的0,同时确定string开始合并的位置。
  • 利用stringbuilder合并
// 设置变量:长度、数组开始更新的位置
int m = num1.length(), n = num2.length(), k = m + n - 2; // 0的情况
if ((m == 1 && num1.equals("0")) || (n == 1 && num2.equals("0"))) return "0"; // 存储两个单数字乘积结果的数组
// 遍历更新数组
int[] record = new int[m+n];
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
// 注意这里要 +=,因为有i+j两次等于相同的数。
// 另外,最后一个位置此时并不会用上。例如99 * 99中,数组里的数分别是[81, 162, 81, 0]
record[k-i-j] += (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
}
} // 将数组的值转化为结果值
// 加总,将各乘积整理成单个数。此处用上最后一个位置,[1 0 8 9]
int carry = 0;
for (int i = 0; i < m + n; i++){
record[i] += carry;
carry = record[i] / 10;
record[i] %= 10;
} // 去掉多余的0,同时确定string开始合并的位置
int i = m + n - 1;
if (record[i] == 0) i--; // 利用stringbuilder合并
StringBuilder res = new StringBuilder();
while (i >= 0) res.append(record[i--]); // 返回结果
return res.toString();

71简化路径

思路:

  • split

  • 遍历,如果不是空和".",那么就判断添加还是删除了

    • 如果不等于"..",添加
    • 否则判断listPath.size()是否大于0,是就去掉最后一个文件
  • 如果遍历后是空的话返回"/",如果有多个"/"只保留一个。

String[] paths = path.split("/");
List<String> res = new ArrayList<>(); for (String str : paths) {
if (!str.isEmpty() && !str.equals(".")){
if (!str.equals("..")) res.add(str);
else {
// 如果是"..",且size() > 0,要去掉最后一个文件
if (res.size() > 0) res.remove(res.size() - 1);
}
}
} if (res.size() == 0) return "/"; StringBuilder builder = new StringBuilder();
for (String re : res) {
builder.append("/").append(re);
} return builder.toString();

93复原IP地址

思路:

  • 新建ArrayList存储结果

  • 创建函数递归寻找四个数字的组合(函数中包含:待检验的string、已确定数量的n,例如1表示已经得出255.xx、目前拼接到的)

    • 遍历1到4,由于每位最多3个数字。如果s剩余的长度不及遍历的数字k,就结束循环。用一位,两位,三位来尝试,判断是否合法val > 255 || k != String.valueOf(val).length()。合法的话,说明配置了一个,递归调用helper时n+1,out + 配置好的值val,另外如果n==3,则要加"."

    • 如果n达到了4,还要检查s是否为空,否则会出现"2.5.5.2"

public static List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<String>();
helper(s, 0, "", res);
return res;
} /**
* @param n 已确定的位数,例如 255. 就确定了一位
* @param out 当前累积的结果,如 255. 或 255.1
*/
public static void helper(String s, int n, String out, List<String> res) {
if (n == 4) {
// 保存结果,s.isEmpty()是最后一段刚好3个数的情况
// 要检查s是否已经为空,否则会出现"2.5.5.2"
if (s.isEmpty()) res.add(out);
return;
} for (int k = 1; k < 4; ++k) {
// 剩余的数可能组不成3个数,如23,此时就没必要尝试k = 3了,否则s.substring(0, k)会outOfIndex
if (s.length() < k) break;
// 用一位,两位,三位来尝试,分别判断其合不合法,如果合法,则调用递归继续分剩下的字符串,最终和求出所有合法组合
int val = Integer.parseInt(s.substring(0, k));
// 比如当k=3时,说明应该是个三位数,但如果字符是"010",那么转为整型val=10,再转回字符串就是"10",此时的长度和k值不同了
if (val > 255 || k != String.valueOf(val).length()) continue;
helper(s.substring(k), n + 1, out + val + (n == 3 ? "" : "."), res);
}
}

60第k个排列

给定 nk,返回第 k 个排列。

思路:

  • 新建一个ArrayList,存储[1, ..., n]
  • 新建一个数组存储[1, 1!, 2!, 3!, ..., n-1!]阶乘
  • k—,把排名转换为下标
StringBuilder sb = new StringBuilder();
for (int i = n; i >= 1; i--) {
// 除以 n - 1 的阶乘,即16/3! = 2,在第三组全排序中
int idx = k / f[i - 1];
// nums.get(idx)取得3
sb.append(nums.get(idx));
// 去掉已选的数字
nums.remove(idx);
// 取余数,更新k在新组中的排名,即第三组中的第16%3! = 4个(0开始)
k %= f[i - 1];
}
return sb.toString();

151翻转字符串里的单词(344反转字符串、557反转字符串中的单词 III)

思路:

  • split
  • 判断是否为空
  • 遍历,从后往前,只要不为空,就添加,并加上空格
  • 返回结果,记得trim
151翻转字符串里的单词
输入: "the sky is blue",
输出: "blue is sky the". 344反转字符串
输入: "A man, a plan, a canal: Panama"
输出: "amanaP :lanac a ,nalp a ,nam A" 557反转字符串中的单词
输入: "Let's take LeetCode contest"
输出: "s'teL ekat edoCteeL tsetnoc"

14最长公共前缀

思路:

  • 取第一个string作为prefix
  • 遍历,从第二个开始
    • 循环,只要str.indexOf(prefix) != 0,prefix去掉最后一个字符
  • 返回prefix

20有效的括号

思路:

  • 新建stack
  • 遍历
    • 遇到做括号入栈
    • 否则,先判断stack是否为空,为空返回false,否则顶层和各个有括号匹配,不匹配返回false
  • 返回stack.isEmpty()

567字符串的排列(了解)

输入: s1 = "ab" s2 = "eidbaooo"
输出: True
解释: s2 包含 s1 的排列之一 ("ba").

思路:

  • 把s1都放进int[128]中,放一个,record[i]++;
  • 遍历s2找匹配,遍历到的都-1
  • 当cnt减到0时,开始判断窗口大小是否刚好等于s1大小,否则缩小left,如果缩小时减去了s1中的值,则cnt+1,继续上一步的遍历。
// 创建数组计数s1的字符
int[] record = new int[128];
for (char i: s1.toCharArray()){
record[i]++;
}
// 遍历,从s2中寻找配对的
for (int right = 0; right < n2; right++){
if (record[s2.charAt(right)]-- > 0) cnt--; // 如果匹配数等于s1的长度,遍历
while(cnt == 0){
// 如果窗口大小刚好与s1的一样,则找到了
if (right - left + 1 == n1) return true;
// 收缩左边界,如果去掉了s1中的字符,那么s1的匹配数+1
if (++record[s2.charAt(left++)] > 0) cnt++;
}
}
return false;

leetcode String相关的更多相关文章

  1. JAVA基础5——与String相关的系列(1)

    与String相关的系列 String, 是JAVA中常见的一个引用类型,且其具有一定的特殊性. String类型被设置为final型,即不可继承,也就不可修改其中的实现. String可以改变吗 S ...

  2. 03匿名内部类、eclipse快捷键、String相关知识

    03匿名内部类.eclipse快捷键.String相关知识-2018.7.11 1.匿名内部类(只针对重写一个方法时候使用,不能向下转型,因为没有子类类名) new Inter(){ public v ...

  3. 【Java基础】String 相关知识点总结

    String 相关知识点总结 字符串的不可变性 概述 String 被声明为 final,因此它不可继承 在 Java8 中,String 内部使用 char 数组存储数据 public final ...

  4. leetcode tree相关题目总结

    leetcode tree相关题目小结 所使用的方法不外乎递归,DFS,BFS. 1. 题100 Same Tree Given two binary trees, write a function ...

  5. [LeetCode] [链表] 相关题目总结

    刷完了LeetCode链表相关的经典题目,总结一下用到的技巧: 技巧 哑节点--哑节点可以将很多特殊case(比如:NULL或者单节点问题)转化为一般case进行统一处理,这样代码实现更加简洁,优雅 ...

  6. [leetcode] 根据String数组构造TreeNode,用于LeetCode树结构相关的测试用例

    LeetCode 跟树结构相关的题目的测试用例中大多是通过String数组来构造树.例如{2,#,3,#,4,#,5,#,6},可以构造出如下的树(将树结构逆时针选择90度显示): 6         ...

  7. Leetcode Lect1 String相关题目

    Java 的 String 类基本用法介绍:http://www.runoob.com/java/java-string.html Java 的 String.substring 函数:https:/ ...

  8. [LeetCode] String to Integer (atoi) 字符串转为整数

    Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. ...

  9. string相关总结

    一 <string> 1 string类常见成员函数 (1)属性相关 s.empty()   s为空时返回true,否则返回false s.size()      返回s中字符的个数,不包 ...

随机推荐

  1. Java_Web三大框架之Struts2

    今天正式接触Java_Web三大框架之Struts2框架.对于初学者来说,先来了解什么是框架技术: 一.“框架技术”帮我们更快更好地构建程序: 1.是一个应用程序的半成品 2.提供可重用的公共结构 3 ...

  2. ajax不执行success的问题

    有时候经常会遇到ajax请求后台,然后后台返回数据后,不触发ajax的success函数的问题,归根到底,这与ajax的参数设置dataType和后台的返回值的类型有关,现总结如下: 一.后台返回值的 ...

  3. Flask 框架构建

    Flask 框架构建,目标构建成Django类似的结构 一. 先看看构建后的效果 # 第一次初始化 python manage.py db init # 生成数据库版本 python manage.p ...

  4. 我所理解的Android和iOS上的View

    View,几乎是所有界面系统中的基类,在iOS里面是UIView,在Android里是View. 那么,到底View是什么东西,他做了些什么,他是怎么做到的,在这篇文章中,希望能带给大家一些启发. 抽 ...

  5. wpf绑定静态变量,模拟rem单位

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; usin ...

  6. 如何在mac里面,把xcode代码同步到 tfs 的 git库(新git库)

    克隆篇请参考:http://www.cnblogs.com/IWings/p/6744895.html 在mac安装visual studio code https://code.visualstud ...

  7. LINUX -- pthread_detach()与pthread_join()

    pthread_detach()即主线程与子线程分离,子线程结束后,资源自动回收. int pthread_join(pthread_t tid, void **thread_return); {su ...

  8. CSS 选择器 知识点

    <html> <head> <style type="text/css"> h1 > strong { /*子元素选择器 只选择自己 的子 ...

  9. LDAP个人理解

    在新的公司办公,所有的后台系统或文档系统都公用一个LDAP账号. 接触到这个新名词,就查了一下,谈谈个人理解: LDAP是个协议, 简单地说,可以把LDAP服务理解为一套存放你账户密码的数据库系统.市 ...

  10. Django REST framework 渲染器、版本

    渲染器.版本: # settings.py REST_FRAMEWORK = { "DEFAULT_RENDERER_CLASSES": [ "rest_framewor ...