Leetcode题库-实现strStr()(java语言版)

题目描述:

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

这道题刚开始看到用java中的字符串indexof方法(找某个字符第一次出现的位置,没有就返回-1)就完美解决,执行用时4ms。

代码如下

public static void main(String[] args){
        Scanner sc  = new Scanner ( System.in );
        String str1 = sc.next ();
        String str2 = sc.next ();
        int num = str1.indexOf ( str2 );
        System.out.println(str2+":第一出现的位置:"+num);
    }

执行结果:

执行用时:

这道题用内置函数没有一点点难度,但是,leetcode是一个练习算法题的地方,这种方法虽然可以解决,但是,没有任何收获。

我会继续补充方法。

这是我今天想到的一种方法,我称为暴力for循环加一个if判断.

代码如下:

//       第二种遍历
        if (str2.length ()==0) {
            System.out.println(0);
        }
        if (str2.length ()>str1.length ()){
            System.out.println(-1);
        }
        //循环遍历第一个字符串,
然后当第二个字符串的长度加上遍历时的变量指针i的值小于等于第一个字符串(没有这行代码,字符串会溢出。)
        //并且,让第一个字符串根据for循环截取i+第二个字符串长度的字符串,
当等于第二个字符串时,停止,返回这时的i,就是第二个字符串第一次出现在第一个字符串里的位置。
        for (int i=0;i<str1.length ();i++){
              if (i+str2.length ()<=str1.length ()&&str1.substring ( i,i+str2.length ()).equals ( str2 )){
                  System.out.println(i);
              }
        }

执行用时:

提交了两次,这种方法都是九秒钟,没有直接用indexof方法来的快。但这种方法也是一种思路,就是遍历第一个字符串,然后截取i(位置指针,从0,1,2,往后移动)到i+上第二个字符串的长度的字符串,与第二个字符串比较,相等则找到了,返回这时的i.

举个例子:字符串string,ing ,求ing在string中第一次出现的位置,从string的第0个字符开始,截取,i+ing长度的字符串。

也就是,第一个截取,str与ing比较,第二次,第二个字符,截取ing长度的字符串。tri与ing比较,直到ing==ing时,返回这时的i.(substring这个方法中,第一个参数是字符的位置,第二个是在这个位置的基础上截取的长度(这个长度是要求的第二个字符串的长度))

这是我的思路,说了一大堆,很绕口,一句话总结就是,截取第一个字符串,与第二个字符串比较,返回对应的位置下标即可。

第三种方法:

         用char数组,然后当i<=第一个字符数组长度-第二个字符数组长度时,循环。例如,string,ing,当i<=3的时候循环,当第一个字符数组第i个字符等于第二个字符数组的第一个字符时,然后循环遍历,第二个字符数组,当第一个字符数组从i开始加j不等于第二个字符数组时,跳出。然后当j=第二个数组长度时,返回此时的i,这就是遍历到第二个字符数组最后那一个字符时输出。

十分绕口的一句话:总结就是,当第一个数组某个字符等于第二个数组第一个字符时,遍历第二个数组,然后从这个相等数组的下一为开始比较,不相同直接跳出,返回-1,相同跳过。

        难点就是:第一个for循环条件是第一个字符数组长度减去第二个。这个其实也好理解。例如,string ,ing.6-3=3,i<=3.第一个for循环结束相等的那个字符正好包括循环内,这样做的好处:

          一,就是为下面的i+j向后移动指针做铺垫;(不然会数组越界)
          二,就是减少遍历的次数,一层循环只遍历一部分,这部分已经包含了与第二个字符数组第一个字符相同的那个字符。

当然,也可以不用这样麻烦,就直接让i<第一个字符数组长度,这样也是可以的,不过就是增加了遍历的次数。

具体看代码:

第三种char数组
        char c1[] = str1.toCharArray ();
        char c2[] = str2.toCharArray ();
//         例如:string ,ing,迭代次数,6-3=3次。当c1--i==c2--i时,迭代c2。判断c1与c2元素是否相等,相等跳过,不相等退出。
        for (int i=0;i<=c1.length-c2.length;i++){
            if (c1[i]==c2[0]){
                int j = 1;
                for (;j<c2.length;j++){
//                    从第i+j个位置开始,就是从c1与c2相等的第二个元素开始比较.
                    if (c1[i+j]!=c2[j]){
                        break;
                    }
                }
                if (j==c2.length){
                    System.out.println(i);
                }
            }
        }
        System.out.println(-1);
    }

执行用时:

总结:本人由于笔记本显示屏出现问题,耽搁一下午时间,博客也写得仓促,本博客不完善,本人能力有限,可能没有好的思路,但会尽力去想。例如kmp算法解决这道题,等我了解了kmp我会单独写一篇博客,敬请期待。

2019-1-25记录

2019-1-26记录

2019-1-28记录

发布了43 篇原创文章 · 获赞 6 · 访问量 6685

猜你喜欢

转载自blog.csdn.net/weixin_37850160/article/details/86653754