【代码随想录】刷题笔记Day13

前言

快要开学了,由于已经整整三四个月没动代码了,码力归0了,花了几天时间把前面的题重新刷了一遍,研一有课也不太能去实习,正好趁此机会继续提高!

151. 反转字符串中的单词

  • 移除多余空格(双指针法,)
  • 将整个字符串反转(反转字符串,左闭右开)
  • 将每个单词反转(空格和最后就翻转)
  • class Solution {
    public:
        void reverse(string& s, int start, int end){ // 翻转,区间写法:左闭右闭 []
            for (int i = start, j = end; i < j; i++, j--) {
                swap(s[i], s[j]);
            }
        }
    
        void removeExtraSpaces(string& s) {// 去除所有空格并在相邻单词之间添加空格, 快慢指针。
            int slow = 0;   // 整体思想参考https://programmercarl.com/0027.移除元素.html
            for (int i = 0; i < s.size(); ++i) {
                if (s[i] != ' ') {   // 遇到非空格就处理,即删除所有空格。
                    if (slow != 0) s[slow++] = ' ';  // 手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
                    while (i < s.size() && s[i] != ' ') {  // 补上该单词,遇到空格说明单词结束。
                        s[slow++] = s[i++];
                    }
                }
            }
            s.resize(slow);  // slow的大小即为去除多余空格后的大小。
        }
    
        string reverseWords(string s) {
            removeExtraSpaces(s);  // 去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。
            reverse(s, 0, s.size() - 1);
            int start = 0;  // removeExtraSpaces后保证第一个单词的开始下标一定是0。
            for (int i = 0; i <= s.size(); ++i) {
                if (i == s.size() || s[i] == ' ') {  // 到达空格或者串尾,说明一个单词结束。进行翻转。
                    reverse(s, start, i - 1); // 翻转,注意是左闭右闭 []的翻转。
                    start = i + 1; // 更新下一个单词的开始下标start
                }
            }
            return s;
        }
    };

剑指 Offer 58 - II. 左旋转字符串

  • 局部反转 + 整体反转,比模拟简单而且空间复杂度只有O(1)
  • class Solution {
    public:
        string reverseLeftWords(string s, int n) {
            reverse(s.begin(), s.begin() + n);
            reverse(s.begin() + n, s.end());
            reverse(s.begin(), s.end());
            return s;
        }
    };

28. 找出字符串中第一个匹配项的下标

  • KMP算法理论理解看视频最浅显易懂的 KMP 算法讲解_哔哩哔哩_bilibili
  • next数组生成图示
  • 以下版本为【next数组版:前缀表统一减1】
  • class Solution {
    public:
        void getNext(int* next, const string& s) {
            int j = -1;
            next[0] = j;
            for(int i = 1; i < s.size(); i++) { // 注意i从1开始
                while (j >= 0 && s[i] != s[j + 1]) { // 前后缀不相同了
                    j = next[j]; // 向前回退
                }
                if (s[i] == s[j + 1]) { // 找到相同的前后缀
                    j++;
                }
                next[i] = j; // 将j(前缀的长度)赋给next[i]
            }
        }
        int strStr(string haystack, string needle) {
            if (needle.size() == 0) {
                return 0;
            }
            int next[needle.size()];
            getNext(next, needle);
            int j = -1; // // 因为next数组里记录的起始位置为-1
            for (int i = 0; i < haystack.size(); i++) { // 注意i就从0开始
                while(j >= 0 && haystack[i] != needle[j + 1]) { // 不匹配
                    j = next[j]; // j 寻找之前匹配的位置
                }
                if (haystack[i] == needle[j + 1]) { // 匹配,j和i同时向后移动
                    j++; // i的增加在for循环里
                }
                if (j == (needle.size() - 1) ) { // 文本串s里出现了模式串t
                    return (i - needle.size() + 1);
                }
            }
            return -1;
        }
    };
    

 后言

KMP算法理解起来真是让人头大,明天开完组会再看看然后模仿着写一下吧~

你可能感兴趣的:(代码随想录刷题笔记,笔记,数据结构,算法,leetcode,职场和发展)