计算机小菜鸡求职刷题笔记-字符串篇

计算机小菜鸡求职刷题笔记-字符串篇

菜鸡一枚,日常记录,部分笔记出自LeetCode题解。

3. 无重复字符的最长子串【滑动窗口】

  • 总结:第一次刷字符串完全没思路啊啊啊,看了题解才知道…滑动窗口的方法。知识点:s.charAt(end)根据索引获取字符串中的字符。
    在这里插入图片描述
class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character,Integer> map=new HashMap<>();
        int ans=0;
        int n=s.length();
        for(int start=0,end=0;end<n;end++){
            if(map.containsKey(s.charAt(end))){
                start = Math.max(map.get(s.charAt(end)),start);
            }
            map.put(s.charAt(end),end+1);
            ans=Math.max(ans,end-start+1);
        }
        return ans;
    }
}

5. 最长回文子串【动态规划/中心扩散】

  • 总结:还是不会…看了答案可采用动态规划和中心扩散两种方法。
  • 知识点: char[] charArray=s.toCharArray(); //字符串转为数组toCharArray() 相较于 charAt() 可以提升用时。
    在这里插入图片描述
  1. 动态规划
class Solution {
    public String longestPalindrome(String s) {
        //动态规划
        int n=s.length();
        int maxLen=1;
        boolean[][] dp=new boolean[n][n];
        if(n<2) return s;

        for(int i=0;i<n;i++){
            dp[i][i]=true;
        }

        char[] charArray=s.toCharArray(); //字符串转为数组
        int begin=0;
        for(int j =1;j<n;j++){
            for(int i=0;i<j;i++){
                if(charArray[i]==charArray[j]){
                    if(j-i<3) dp[i][j]=true;
                    else dp[i][j]=dp[i+1][j-1];
                }else{
                    dp[i][j]=false;
                }

                if(dp[i][j]==true&&j-i+1>maxLen){
                    maxLen=j-i+1;
                    begin=i;
                }
            }
        }
        return s.substring(begin,begin+maxLen);
    }
}
  1. 中心扩散
class Solution {
    public String longestPalindrome(String s) {
        if (s == null || s.length() < 1){
            return "";
        }

        // 初始化最大回文子串的起点和终点
        int start = 0;
        int end   = 0;

        // 遍历每个位置,当做中心位
        for (int i = 0; i < s.length(); i++) {
            // 分别拿到奇数偶数的回文子串长度
            int len_odd = expandCenter(s,i,i);
            int len_even = expandCenter(s,i,i + 1);
            // 对比最大的长度
            int len = Math.max(len_odd,len_even);
            // 计算对应最大回文子串的起点和终点
            if (len > end - start){
                start = i - (len - 1)/2;
                end = i + len/2;
            }
        }
        // 注意:这里的end+1是因为 java自带的左闭右开的原因
        return s.substring(start,end + 1);
    }


    /**
     *
     * @param s             输入的字符串
     * @param left          起始的左边界
     * @param right         起始的右边界
     * @return              回文串的长度
     */
    private int expandCenter(String s,int left,int right){
        // left = right 的时候,此时回文中心是一个字符,回文串的长度是奇数
        // right = left + 1 的时候,此时回文中心是一个空隙,回文串的长度是偶数
        // 跳出循环的时候恰好满足 s.charAt(left) != s.charAt(right)
        while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
            left--;
            right++;
        }
        // 回文串的长度是right-left+1-2 = right - left - 1
        return right - left - 1;
    }
}

14. 最长公共前缀 【横向扫描/分治法】

  • 总结:
  1. 横向扫描
    在这里插入图片描述
class Solution {
    public String longestCommonPrefix(String[] strs) {
        if(strs==null||strs.length==0) return "";
        String ans=strs[0];
        int n=strs.length;

        for(int i=1;i<n;i++){
            int j=0;
            for(;j<ans.length()&&j<strs[i].length();j++){

                if(strs[i].charAt(j)!=ans.charAt(j)) break;
            }
            ans=ans.substring(0,j);
            if(ans=="") return "";
        }
        return ans;
    }
}
  1. 分治法
    在这里插入图片描述
class Solution {
    public String longestCommonPrefix(String[] strs) {
        //分治法
        if(strs==null||strs.length==0) return "";
        else return longestCommonPrefix(strs,0,strs.length-1);
    }
    
    public String longestCommonPrefix(String[] strs,int left,int right){
        if(left==right) return strs[left];
        int mid=(right+left)/2;
        String prefix1=longestCommonPrefix(strs,left,mid);
        String prefix2=longestCommonPrefix(strs,mid+1,right);

        int i=0;
        for(;i<prefix1.length()&&i<prefix2.length();i++){
            if(prefix1.charAt(i)!=prefix2.charAt(i)) break;
        }
        return prefix1.substring(0,i);
    } 
}

38. 字符串的排序【回溯法】

  • 总结:好难啊啊啊啊啊啊啊回溯法
lass Solution {
    List<String> res = new LinkedList<>();
    char[] c;
    public String[] permutation(String s) {
        c = s.toCharArray();
        dfs(0);
        return res.toArray(new String[res.size()]);
    }
    void dfs(int x) {
        if(x == c.length - 1) {
            res.add(String.valueOf(c));      // 添加排列方案
            return;
        }
        HashSet<Character> set = new HashSet<>();
        for(int i = x; i < c.length; i++) {
            if(set.contains(c[i])) continue; // 重复,因此剪枝
            set.add(c[i]);
            swap(i, x);                      // 交换,将 c[i] 固定在第 x 位
            dfs(x + 1);                      // 开启固定第 x + 1 位字符
            swap(i, x);                      // 恢复交换
        }
    }
    void swap(int a, int b) {
        char tmp = c[a];
        c[a] = c[b];
        c[b] = tmp;
    }
}

22. 括号生成【回溯法】

  • 总结:回溯法还是不太熟,开了新的刷题进度恶补一下…
class Solution {
    List<String> res=new ArrayList<>();

    public List<String> generateParenthesis(int n) {
        StringBuilder strs=new StringBuilder();
        backtrack(strs,0,0,n);
        return res;
    }

    void backtrack(StringBuilder track, int open,int close, int max){
        if(track.length()==max*2){
            res.add(track.toString());
            return;
        }
        if(open<max){
            track.append("(");
            backtrack(track,open+1,close,max);
            track.deleteCharAt(track.length()-1);
        }
        if(close<open){
            track.append(")");
            backtrack(track,open,close+1,max);
            track.deleteCharAt(track.length()-1);
        }

    }

}

28. 实现 strStr()【KMP】

class Solution {
    //KMP
    public void getNext(int[] next, String s){
        //j表示前缀末尾位置, i表示后缀末尾位置
        //next[i]=j
        int j=0;
        next[0]=j;

        for(int i=1;i<s.length();i++){
            while(j>0&&s.charAt(i)!=s.charAt(j)){
                j=next[j-1];
            }

            if(s.charAt(i)==s.charAt(j)){
                j++;
                next[i]=j;
            }
        }
        return;
    }
    
    public int strStr(String haystack, String needle) {
        if(needle.length()==0) return 0;
        if(haystack.length()==0) return -1;
        
        int[] next=new int[needle.length()];
        getNext(next,needle);

        int j=0;//模式串
        for(int i=0;i<haystack.length();i++){//文本串
            while(j>0&&haystack.charAt(i)!=needle.charAt(j)){
                j=next[j-1];
            }

            if(haystack.charAt(i)==needle.charAt(j)){
                j++;
            }

            if(j==needle.length()) return i-needle.length()+1;

        }
        return -1;

    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值