zoukankan      html  css  js  c++  java
  • leetcode Longest Substring Without Repeating Characters 没有重复字符的最长子字符串

    在做该题时,一开始思路是对的,但是写法不同,效率截然不同

    // 第一个写法,提交时一个几十位的字符串,提示time limit exceeded,后来在本地运行了以下,效率5ms

    private static int method1(String s) {

    long start = System.currentTimeMillis();

    if (s.equals("")) {

    return 0;

    }

    int length = 1;

    int i = 0;

    while (i < s.length() - 1) {

    for (int j = i + 1; j <= s.length() - 1; j++) {

    System.out.println(i + "----" + j);

    String sub = s.substring(i, j);

    if (!sub.contains(String.valueOf(s.charAt(j)))) {

    System.out.println(sub + "----" + s.charAt(j));

    int l = j - i + 1;

    if (l > length) {

    length = l;

    }

    // 最后j到了s的末尾之后,i也可以结束了

    if (j == s.length() - 1) {

    i = s.length() - 1;

    }

    else {

    i = j;

    break;

    }

    }

    }

    long end = System.currentTimeMillis();

    System.out.println("程序运行时间:" + (end - start) + "ms");

    return length;

    }

    // 第二种写法,stringbuffer替代string,跟method1相比,超时的字符串,效率提升1ms,但是依然不够

    private static int method2(String s) {

    long start = System.currentTimeMillis();

    if (s.equals("")) {

    return 0;

    }

    int length = 1;

    int i = 0;

    StringBuffer sub = new StringBuffer("");

    while (i < s.length() - 1) {

    for (int j = i + 1; j <= s.length() - 1; j++) {

    System.out.println(i + "----" + j);

    sub.setLength(0);

    sub = sub.append(s.substring(i, j));

    if (!sub.toString().contains(String.valueOf(s.charAt(j)))) {

    System.out.println(sub + "----" + s.charAt(j));

    int l = j - i + 1;

    if (l > length) {

    length = l;

    }

    // 最后j到了s的末尾之后,i也可以结束了

    if (j == s.length() - 1) {

    i = s.length() - 1;

    }

    } else {

    i = j;

    break;

    }

    }

    }

    long end = System.currentTimeMillis();

    System.out.println("程序运行时间:" + (end - start) + "ms");

    return length;

    }

    //运用纯指针的写法,而不是依次遍历,效率提升非常明显,前两种方法超时的字符串,只需要0ms,但是,几百位的字符串,依然超时

    private static int method3(String s) {

    long start = System.currentTimeMillis();

    if (s.equals("")) {

    return 0;

    }

    int length = 1;

    int i = 0;

    int j = 1;

    StringBuffer sub = new StringBuffer("");

    while (i <= s.length() - 1 && j <= s.length() - 1) {

    sub.setLength(0);

    sub.append(s.substring(i, j));

    if (sub.toString().contains(String.valueOf(s.charAt(j)))) {

    if (j - i > length) {

    length = j - i;

    }

    i = i + sub.toString().indexOf(s.charAt(j)) + 1;

    j = i + 1;

    } else {

    if (j == s.length() - 1) {

    if (j - i + 1 > length) {

    length = j - i + 1;

    }

    break;

    }

    j++;

    }

    }

    long end = System.currentTimeMillis();

    System.out.println("程序运行时间:" + (end - start) + "ms");

    return length;

    }

    做到此时已经是有点头大,所以百度了一下大众的写法,其中绝大部分都用到了hashmap来进行记录,想必是通过map来记录是否有重复,从而取代了我用来判断是否重复的方法 即string的contains方法,比如以下一位大神的写法

    public int lengthOfLongestSubstring(String s) {
    HashMap<character, integer=""> map = new HashMap<character, integer="">();
    if (s == null || s.length() == 0) return 0;
    if (s.length() == 1) return 1;
    int rightPointer = 0, leftPointer = rightPointer - 1, answer = 0;
    while (rightPointer != s.length()) {
    Integer previousOccurrence = map.put(s.charAt(rightPointer), rightPointer);
    if (previousOccurrence != null) {
    leftPointer = Math.max(leftPointer, previousOccurrence);
    }
    answer = Math.max(answer, rightPointer - leftPointer);
    rightPointer++;
    }
    return answer;
    }

    所以,自己转换了以下思路,写出了如下代码,accepted,如此可见java中Collection的重要性

    public class Solution {
    public int lengthOfLongestSubstring(String s) {
    long start = System.currentTimeMillis();
    if (s == null || s.equals("")) {
    return 0;
    }
    Map<Character, Integer> map = new HashMap<Character, Integer>();
    map.put(s.charAt(0), 0);
    int length = 1;
    int left = 0;
    int right = 1;
    while (right < s.length()) {
    // System.out.println("left:"+left+"------right:" + right);
    // 如果key存在了,那么put方法返回的是之前存入的值
    Integer loc = map.put(s.charAt(right), right);
    // System.out.println(map.get(s.charAt(right)));
    if (loc != null) {// 说明left到right之间,包含了s.charAt(right),即该没有重复的字符串到此为止
    // 判断
    if (left <= loc) {
    if (right - left > length) {
    length = right - left;
    }
    left = loc + 1;
    right ++;//假设right未加1前,值为n,字符为‘d’,right此处不能为left+1,因为当right的值之前存在过,left=loc+1后,left跟right之间肯定是没有重复字符的
    //而且,当right=left+1,不仅有的字符又重新遍历了一遍,而且right相当于回退了,d的value已经是n,再重新遍历到d时,left一定是小于n的,实际上left比较的应该是再之前d对应的value,不应该出现这种情况,参考"dvdf"
    }else{
    right++;
    }
    } else {
    right++;
    }
    }
    if (right - left > length) {
    length = right - left;
    }
    long end = System.currentTimeMillis();
    System.out.println("程序运行时间:" + (end - start) + "ms");
    return length;
    }
    }

    实际上,在此方法中,一方面是特别注视的地方,此处有bug,查找了半天。另一方面,总是提示超时,后来发现是sysout的原因。

    另外,里面的if写法还可以优化。

     

     

  • 相关阅读:
    【记录】【MySQL】填充字符串函数 LPAD(str,len,padstr)
    nvm安装node和npm,个人踩坑记录
    win10系统下cmd输入一下安装的软件命令提示拒绝访问解决办法
    bootstrap大图轮播手机端不能手指滑动解决办法
    JS中函数声明与函数表达式的异同
    javaScript实现归并排序
    js插入节点appendChild和insertBefore
    JS的事件冒泡和事件捕获
    js 停止事件冒泡 阻止浏览器的默认行为
    事件绑定的几种常见方式
  • 原文地址:https://www.cnblogs.com/govoid/p/4975592.html
Copyright © 2011-2022 走看看