• 刷题记录----字符串


    目录

    刷题记录----字符串

    反转字符串

    反转字符串||

    替换空格

    翻转字符串里的单词

    左旋字符串

    KMP算法经典题目

    实现strStr()

    next数组----存储模式串的最长相等前后缀

    构造next数组

    重复的子字符串


    刷题记录----字符串

    反转字符串

    class Solution {
        public void reverseString(char[] s) {
            int l = 0;
            int r = s.length - 1;
            while (l < r) {
                s[l] ^= s[r];  //构造 a ^ b 的结果,并放在 a 中
                s[r] ^= s[l];  //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b
                s[l] ^= s[r];  //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换
                l++;
                r--;
            }
        }
    }
    ​

    反转字符串||

    给定一个字符串 s 和一个整数 k,你需要对从字符串开头算起的每隔 2k 个字符的前 k 个字符进行反转。

    如果剩余字符少于 k 个,则将剩余字符全部反转。

    如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

    class Solution {
        public String reverseStr(String s, int k) {
            char[] ch = s.toCharArray();
            // 1. 每隔 2k 个字符的前 k 个字符进行反转
            for (int i = 0; i< ch.length; i += 2 * k) {
                // 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
                if (i + k <= ch.length) {
                    reverse(ch, i, i + k -1);
                    continue;
                }
                // 3. 剩余字符少于 k 个,则将剩余字符全部反转
                reverse(ch, i, ch.length - 1);
            }
            return  new String(ch);
    ​
        }
        // 定义翻转函数
        public void reverse(char[] ch, int i, int j) {
        for (; i < j; i++, j--) {
            char temp  = ch[i];
            ch[i] = ch[j];
            ch[j] = temp;
        }
    ​
        }
    }

    替换空格

    class Solution {
    public:
        string replaceSpace(string s) {
            int count = 0; // 统计空格的个数
            int sOldSize = s.size();
            for (int i = 0; i < s.size(); i++) {
                if (s[i] == ' ') {
                    count++;
                }
            }
            // 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
            s.resize(s.size() + count * 2);
            int sNewSize = s.size();
            // 从后先前将空格替换为"%20"
            for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
                if (s[j] != ' ') {
                    s[i] = s[j];
                } else {
                    s[i] = '0';
                    s[i - 1] = '2';
                    s[i - 2] = '%';
                    i -= 2;
                }
            }
            return s;
        }
    };
    ​

    翻转字符串里的单词

    左旋字符串

    把字符串前n个字母翻转到末尾

    1. 反转区间为前n的子串

    2. 反转区间为n到末尾的子串

    3. 反转整个字符串

    class Solution {
        public String reverseLeftWords(String s, int n) {
            int len=s.length();
            StringBuilder sb=new StringBuilder(s);
            reverseString(sb,0,n-1);
            reverseString(sb,n,len-1);
            return sb.reverse().toString();
        }
         public void reverseString(StringBuilder sb, int start, int end) {
            while (start < end) {
                char temp = sb.charAt(start);
                sb.setCharAt(start, sb.charAt(end));
                sb.setCharAt(end, temp);
                start++;
                end--;
                }
            }
    }
    ​

    KMP算法经典题目

    实现strStr()

    文本串 aabaabaaf

    模式串 aabaaf

    前缀:包含首字母不含尾字母的字符串

    后缀:......

    next数组----存储模式串的最长相等前后缀

    a0
    aa1
    aab0
    aaba1
    aabaa2
    aabaaf0

    可以发现不匹配的位置是f,那么就跳转到f前一个下标对应的值处,也就是2再接着匹配

    时间复杂度O(n+m)

    构造next数组

    1. 初始化

      定义两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。

    2. 处理前后缀不相同的情况

      j回退----j = next[j-1];

    3. 处理前后缀相同的情况

      j++

    class Solution {
        
        public int strStr(String haystack, String needle) {
            if (needle.length() == 0) return 0;
            int[] next = new int[needle.length()];
            getNext(next, needle);
    ​
            int j = 0;
            for (int i = 0; i < haystack.length(); i++) {
                while (j > 0 && needle.charAt(j) != haystack.charAt(i)) 
                    j = next[j - 1];
                if (needle.charAt(j) == haystack.charAt(i)) 
                    j++;
                if (j == needle.length()) 
                    return i - needle.length() + 1;
            }
            return -1;
    ​
        }
        
        private void getNext(int[] next, String s) {
            int j = 0;
            next[0] = 0;
            for (int i = 1; i < s.length(); i++) {
                while (j > 0 && s.charAt(j) != s.charAt(i)) 
                    j = next[j - 1];
                if (s.charAt(j) == s.charAt(i)) 
                    j++;
                next[i] = j; 
            }
        }
    }
    ​

    重复的子字符串

    给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。

    如果len % (len - next[len - 1] ) == 0 ,则说明 (数组长度-最长相等前后缀的长度) 正好可以被 数组的长度整除,说明有该字符串有重复的子字符串。

    数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。

    class Solution {
    public:
        void getNext (int* next, const string& s){
            next[0] = 0;
            int j = 0;
            for(int i = 1;i < s.size(); i++){
                while(j > 0 && s[i] != s[j]) {
                    j = next[j - 1];
                }
                if(s[i] == s[j]) {
                    j++;
                }
                next[i] = j;
            }
        }
        bool repeatedSubstringPattern (string s) {
            if (s.size() == 0) {
                return false;
            }
            int next[s.size()];
            getNext(next, s);
            int len = s.size();
            if (next[len - 1] != 0 && len % (len - (next[len - 1] )) == 0) {
                return true;
            }
            return false;
        }
    };
    ​

  • 相关阅读:
    漏洞分析丨HEVD-11.DoubleFetch[win7x86]
    Design a Facebook NewsFeed
    云栖大会,未来万物皆是计算机?
    基于网络表示学习的 新闻推荐算法研究与系统实现
    基于nodejs+vue电子病历管理系统-计算机毕业设计
    配置nginx反向代理,监控https流量
    学习笔记:机器学习之支持向量机(五、线性支持向量机-合页损失函数)
    codeblocks提示没有编译器,安装MinGW及运行heloword的方法
    mybatis 批量插入和批量修改
    含文档+PPT+源码等]精品springboot+VUE的学生宿舍管理系统设计与实现[包运行成功]Java毕业设计SSM项目源码
  • 原文地址:https://blog.csdn.net/HandsomeDog_L/article/details/126071876