算法通关村——字符串问题解析

反转的问题

反转字符串

LeetCode344 Easy

class Solution {
    public void reverseString(char[] s) {
        // 双指针地运用
        if (s == null || s.length == 0) {
            return;
        }
        int n = s.length;
        for (int left = 0, right = n - 1;left < right ;left++, right--) {
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
        }
    }
}

K个一组反转

LeetCode541 Easy

情况一

当我们的字符串的长度满足 恰好 right 就是最后一个的情况

情况二

情况三

right 的索引位置超过了,数组的索引长度,现在就体现到了代码之中的 Math.min(r, len - 1 ) 这里就会防止数组越界而且还满足题意。

class Solution {
    public String reverseStr(String s, int k) {
        char[] chars = s.toCharArray();
        int len = s.length();
        for (int l = 0; l < len; l = l + 2 * k) {
            int r = l + k - 1;
            reverse(chars, l, Math.min(r, len - 1));
        }
        return String.valueOf(chars);
    }

    // 翻转对应的字符串
    public void reverse(char[] c, int left, int right) {
        while (left < right) {
            char temp = c[left];
            c[left] = c[right];
            c[right] = temp;
            left++;
            right--;
        }
    }
}

仅仅反转字母

LeetCode.917 Easy

方法一:使用栈

class Solution {
    public String reverseOnlyLetters(String s) {
        char[] chars = s.toCharArray();
        int len = s.length();
        Stack<Character> letters = new Stack<>();
        for (char c : chars) {
            if (Character.isLetter(c)) {
                letters.push(c);
            }
        }

        // 出栈在进行填充
        StringBuilder sb = new StringBuilder();
        for (char c : chars) {
            if (Character.isLetter(c)) {
                sb.append(letters.pop());
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }
}

方法二:使用双子针

两个指针:一个指针 i 初始位置是在 index 为 0 的位置,一个指针 j 初始位置是在 index 为 len - 1 的位置,其中 j 是把所谓的字母加到前面的一个指针,j 这个指针不关心 特殊字符的位置 的位置

class Solution {
    public String reverseOnlyLetters(String S) {
       if (S == null || S.length() == 0) {
            return S;
        }
        StringBuilder ans = new StringBuilder();
        int j = S.length() - 1;
        for (int i = 0; i < S.length(); ++i) {
            if (Character.isLetter(S.charAt(i))) {
                while (!Character.isLetter(S.charAt(j))) {
                    j--;
                }
                ans.append(S.charAt(j--));
            } else {
                // 要以 i 存在的 - 为主,如果 j 位置是 - 那么直接向前移动到上一个 
                ans.append(S.charAt(i));
            }
        }

        return ans.toString();
    }
}

反转字符串里面的单词

151. 反转字符串中的单词 Medium

class Solution {
    public String reverseWords(String s) {
        StringBuilder sb = trimSpaces(s);

        // 翻转字符串
        reverse(sb, 0, sb.length() - 1);

        // 翻转每个单词
        reverseEachWord(sb);

        return sb.toString();
    }

    public StringBuilder trimSpaces(String s) {
        int left = 0, right = s.length() - 1;
        // 去掉字符串开头的空白字符
        while (left <= right && s.charAt(left) == ' ') {
            ++left;
        }

        // 去掉字符串末尾的空白字符
        while (left <= right && s.charAt(right) == ' ') {
            --right;
        }

        // 将字符串间多余的空白字符去除
        StringBuilder sb = new StringBuilder();
        while (left <= right) {
            char c = s.charAt(left);

            if (c != ' ') {
                sb.append(c);
            } else if (sb.charAt(sb.length() - 1) != ' ') {
                sb.append(c);
            }

            ++left;
        }
        return sb;
    }

    public void reverse(StringBuilder sb, int left, int right) {
        while (left < right) {
            char tmp = sb.charAt(left);
            sb.setCharAt(left++, sb.charAt(right));
            sb.setCharAt(right--, tmp);
        }
    }


    public void reverseEachWord(StringBuilder sb) {
        int n = sb.length();
        int start = 0, end = 0;

        while (start < n) {
            // 循环至单词的末尾
            while (end < n && sb.charAt(end) != ' ') {
                ++end;
            }
            // 翻转单词
            reverse(sb, start, end - 1);
            // 更新start,去找下一个单词
            start = end + 1;
            ++end;
        }
    }
}

这段代码写的我吐血🤣

验证回文串

验证回文字符串,一般的思路是双指针。而且回文问题在链表中是重点,在字符串中同样是个重点。

125. 验证回文串 Easy

class Solution {
    public boolean isPalindrome(String s) {
        if (s == null && s.length() == 0) {
            return false; 
        }
        StringBuilder sb = new StringBuilder();
        for (char c : s.toCharArray()) {
            if (Character.isLetterOrDigit(c)) {
                sb.append(Character.toLowerCase(c));
            }
        }
        
        int left = 0, right = sb.length() - 1;
       
        while (left < right) {
            if (sb.charAt(left) != sb.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

字符串中的第一个唯一字符

LeetCode387 Easy

我们使用 Hash 表格记录每一个字符出现的次数,让后遍历 Hash 表格,我们最后找到 Hash 表格之中对应的第一个值为一的索引所在的位置

class Solution {
    public int firstUniqChar(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        Map<Character, Integer> frequency = new HashMap<>();
        for (char ch : s.toCharArray()) {
            frequency.put(ch, frequency.getOrDefault(ch, 0) + 1);
        }

        for (int i = 0; i < s.length(); i++) {
            if (frequency.get(s.charAt(i)) == 1) {
                return i;
            }
        }
        return -1;
    }
}

判定是否互为字符重排

242. 有效的字母异位词

    public boolean checkPermutation(String s1, String s2) {
        // 将字符串转换成字符数组
        char[] s1Chars = s1.toCharArray();
        char[] s2Chars = s2.toCharArray();
        // 对字符数组进行排序
        Arrays.sort(s1Chars);
        Arrays.sort(s2Chars);
        // 再将字符数组转换成字符串,比较是否相等
        return new String(s1Chars).equals(new String(s2Chars));
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Levenshtein Distance算法是一种常见的字符串相似度算法,也被称为编辑距离算法。其主要思想是通过计算两个字符串之间的编辑距离来确定它们的相似程度。 编辑距离指的是将一个字符串转换成另一个字符串所需的最少操作次数,其中每次操作可以是插入、删除或替换一个字符。例如,将字符串“kitten”转换成字符串“sitting”需要进行3次操作,即将“k”替换为“s”,将“e”替换为“i”,将“n”替换为“g”。 Levenshtein Distance算法的实现一般使用动态规划的方法,通过填充一个二维矩阵来计算两个字符串之间的编辑距离。具体实现过程可以参考以下伪代码: ``` function LevenshteinDistance(s1, s2): m = length(s1) n = length(s2) d = new matrix(m+1, n+1) for i from 0 to m: d[i, 0] = i for j from 0 to n: d[0, j] = j for j from 1 to n: for i from 1 to m: if s1[i] == s2[j]: cost = 0 else: cost = 1 d[i, j] = min(d[i-1, j]+1, d[i, j-1]+1, d[i-1, j-1]+cost) return d[m, n] ``` 在以上代码中,变量s1和s2分别表示两个待比较的字符串,m和n分别表示它们的长度,矩阵d用于存储编辑距离的计算结果。首先,将矩阵d的第一行和第一列分别初始化为0到n和0到m的整数。然后,对于每个(i, j)位置,如果s1[i]等于s2[j],则将cost设为0,否则设为1。最后,根据递推公式d[i, j] = min(d[i-1, j]+1, d[i, j-1]+1, d[i-1, j-1]+cost)来填充矩阵d,并返回d[m, n]作为编辑距离的结果。 Levenshtein Distance算法的时间复杂度为O(m*n),其中m和n分别为两个字符串的长度。在实际应用中,该算法可用于拼写检查、数据去重等场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值