leetCode刷题(四)

无重复字符的最长子串

题目链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

这道题拿到后脑子里想到的只有暴力求解的方法,但显然是不可取的。看了题解之后学到了利用滑动窗口的方法求解。滑动窗口这个词我个人认为名字取的很生动形象。因为窗口我们大家都熟悉,它的大小一般是固定的。滑动窗口的概念在很多算法和应用中都有体现,比如在TCP协议中使用相应的滑动窗口协议实现重传恢复。滑动窗口算法可以用以解决数组/字符串的子元素问题,它可以将嵌套的循环问题,转换为单循环问题,降低时间复杂度。
题目解析:
我们先从最左边开始,定义一个空的set容器,如果容器中没有某个字符,就将其添加到容器中,如果向右遍历的过程中遍历到容器中存在了这个字符,则记录下此时的长度。然后从左边第2位开始,相当于将窗口右移一位。重复上面的操作,当向右遍历的时候遍历到的字符在容器中存在了,则记录下此时的长度,调用Math中的取最大值函数记录下较大的那个长度。最后当窗口移动到最右端的时候结束运算。此时ans中记录的大小就是长度最大的无重复字符的子串。

 public static int lengthOfLongestSubstring(String s) {
     
        Set a = new HashSet();
        int n = s.length();
        int right = 0,ans=0;
        for (int i=0;i<n;i++){
     
        //窗口右移一位,在代码中体现就是将容器中最左边的元素移除
            if (i!=0){
     
                a.remove(s.charAt(i-1));
            }
            //当容器中没有该字符时将其添加到容器中
            while (right<n&&!a.contains(s.charAt(right))){
     
                a.add(s.charAt(right));
                ++right;
            }
            //记录最大的子串长度
            ans = Math.max(ans,right-i);
        }
        return ans;
    }

最长回文子串

题目链接:https://leetcode-cn.com/problems/longest-palindromic-substring/
这道题官服题解中给出了三种解法,原谅我能力有限,第三种解法确实比较复杂,也比较难理解。但是第二种解法就相对要好理解很多。它的核心思想是以给定的字符串中的任意一个字符为中心,向两边进行扩展。由于回文字符串的特性,如果ababa是回文子串,则去掉首尾的两个字符,即bab也肯定是回文子串。所以我们就可以向外扩展,扩展到不是回文子串时退出。这就是题解中提到的中心拓展法。

 public static String longestPalindrome(String s) {
     
            if (s == null || s.length() < 1) return "";
            int start = 0, end = 0;
            for (int i = 0; i < s.length(); i++) {
     
                //len1的第一次判断是必定成立的,因为单个字符的时候必定是回文子串
                int len1 = expandAroundCenter(s, i, i);
                //len2是考虑到回文子串时相邻的情况,如abb这种。因为如果是这种情况向两边同时扩展的时候有可能a,b是不同的。
                int len2 = expandAroundCenter(s, i, i + 1);
                int len = Math.max(len1, len2);
                if (len > end - start) {
     
                    start = i - (len - 1) / 2;
                    end = i + len / 2;
                }
            }
            //由于题目需要返回的是子串而不是长度,所以需要根据起始位置截取子串
            return s.substring(start, end + 1);
    }
    //拓展法,其中L--,R++的时候就是向两边进行拓展
    private static int expandAroundCenter(String s, int left, int right) {
     
        int L = left, R = right;
        while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
     
            L--;
            R++;
        }
        return R - L - 1;
    }

leecode的中等难度的题目对我来说已经有点难了,基本上靠自己硬想的话很难想到比较好的解决方法。不知道其他道友刷题的时候是怎么样的,我觉的一开始想不出的话先看看题解然后根据题解结合自己的理解再去尝试写代码,效率会比较高。刷到一定的数量的时候再尝试自己想办法去独立解决。否则一开始就上手硬写感觉效果并不会很好。看别人的经验总结我觉的还是很有帮助的~

你可能感兴趣的:(LeetCode,leetcode,算法)