day17

【0151.翻转字符串里的单词】

  • class Solution {
    public:
        string reverseWords(string s) {
            int slow = 0;
            int fast = 1;
            while (fast < s.size()) {
                if (s[slow] == ' ' && s[fast] == ' ') {
                    fast++;
                }
                if (s[slow] == ' ' && s[fast] != ' ') {
                    slow++;
                    fast++;
                }
            }
        }
    };
    
  • 看懂了 本题是要分三步走 但第一步 移除多余空格 两种方法我都想不通 目前只打算看第二种方法

class Solution {
public:
    void cleanExtraSpace(string &s) {
        int slow = 0;
        for (int fast = 0; fast < s.size(); fast++) {
            while (s[fast] == ' ' && s[++fast] == ' ') {
                slow = fast
            }
        }
    }
    string reverseWords(string s) {
        cleanExtraSpace(s);
    }
};
  • 步骤一:删除多余空格元素 我写的思路是找到多余空格处 进行删除操作 但其实卡哥的思路是 去除所有空格(即先忽略所有空格) 同时在相邻单词之间添加空格 以下三段代码 分别是 标准答案--我的---我的---都是我的
void removeExtraSpaces(string& s) {
	int slow = 0;   
    for (int i = 0; i < s.size(); ++i) { 
    	if (s[i] != ' ') { 
        	if (slow != 0) 
                s[slow++] = ' '; 
        	while (i < s.size() && s[i] != ' ') { 
        		s[slow++] = s[i++];
       		}
        }
    }
    s.resize(slow);
 }
void removeExtraSpaces(string& s) {
	int slow = 0;   
    while(i < s.size()) { 
            while (s[i] != ' ' && i < s.size()) {
                s[slow++] = s[i++];
            }
            s[slow++] = ' ';
     }
     s.resize(slow);
 }
    • 我的1 这段代码 溢出 我就把while改成了for 就解决了 但为什么我i还需要再看看。
void removeExtraSpaces(string& s) {
	int slow = 0;   
    for (int i = 0; i < s.size(); i++) { 
            while (s[i] != ' ' && i < s.size()) {
                s[slow++] = s[i++];
            }
            s[slow++] = ' ';
     }
     s.resize(slow);
 }
    • 我的2 这段代码 运行结果"blue方框 is sky the" 预期结果"blue is sky the" 我知道是因为在for循环里 我每while记录一个单词 最后都slow赋值为空格 那么就意味着我给最后一个单词的结尾也赋了空格 而这是不需要的 经过之后的整串---整个单词的反转 这个空格就会从串末尾---串开头----第一个单词的末尾 这个结果 所以我打算 把最后传的数组大小由slow改成slow-1
void removeExtraSpaces(string& s) {
	int slow = 0;   
    for (int i = 0; i < s.size(); i++) { 
            while (s[i] != ' ' && i < s.size()) {
                s[slow++] = s[i++];
            }
            s[slow++] = ' ';
     }
     s.resize(slow-1);
 }
    • 上个问题解决了 但 输入" hello world " 我的输出"world hello " 预期输出"world hello" 表示原本串开头的那个空格我没删除 那是因为 如果串原本开头是空 那么我进入for 不执行while 却还要执行slow赋值空格这一操作 所以 在for循环里 while循环之前 需要添加一个判断 if操作
void removeExtraSpaces(string& s) {
	int slow = 0;   
    for (int i = 0; i < s.size(); i++) { 
           if (s[i] != ' ') {
                while (s[i] != ' ' && i < s.size()) {
                s[slow++] = s[i++];
                }
                s[slow++] = ' '; 
            }
     }
     s.resize(slow-1);
 }
  • 步骤二:反转整串 和 步骤三:反转每个单词 调用的子函数一样 较简单
  • 但是 关于步骤三 主函数里 先要确定出每个单词的左右区间 然后才能调用子函数进行区间内反转 下面注释掉的 是原标准答案 对应部分代码是我的
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;   
        for (int i = 0; i < s.size(); ++i) { 
            if (s[i] != ' ') { 
                if (slow != 0) s[slow++] = ' '; 
                while (i < s.size() && s[i] != ' ') { 
                    s[slow++] = s[i++];
                }
            }
        }
        s.resize(slow);
    }
    string reverseWords(string s) {
        removeExtraSpaces(s); 
        reverse(s, 0, s.size() - 1);
        //int start = 0; 
        //for (int i = 0; i <= s.size(); ++i) {
        //    if (i == s.size() || s[i] == ' ') {
        //        reverse(s, start, i - 1); 
        //        start = i + 1; 
        //    }
        //}
        int start = 0;
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == ' ') {
                reverse(s, start, i - 1);
                start = i + 1;
            }
            if (i == s.size() - 1) {
                reverse(s, start, i);
            }
        }
        return s;
    }
};
  • 不知道为什么 我的代码可以简写成卡哥那样的 把局部代码拎出来 以下三段代码是等价的 但不知道怎么能写出来后者。还需要再看看。
int start = 0;
for (int i = 0; i < s.size(); i++) {
	if (s[i] == ' ') {
     	reverse(s, start, i - 1);
     	start = i + 1;
	}
	if (i == s.size() - 1) {
      	reverse(s, start, i);
	}
}
for (int i = 0; i <= s.size(); ++i) {
//for (int i = 1; i <= s.size(); i++) {
	if (i == s.size() || s[i] == ' ') { 
       	reverse(s, start, i - 1);
       	start = i + 1; 
     }
}

【剑指Offer58-II.左旋转字符串】

class Solution {
public:
    string reverseLeftWords(string s, int n) {
        int oldSize = s.size();
        s.resize(oldSize + n);
        for (int i = 0; i < n; i++) {
            s[i + oldSize] = s[i];
        }
        for (int i = n; i < s.size(); i++) {
            s[i - n] = s[i];
        }
        s.resize(oldSize);
        return s;
    }
};
  • 运行成功 但我做的没有意义 因为申请了额外空间 想想不申请有什么办法没
class Solution {
public:
    void reverseStr(string &s, int left, int right) {
        for (; left < right; left++, right--) {
            swap(s[left], s[right]);
        }
    }
    string reverseLeftWords(string s, int n) {
        reverseStr(s, 0, n-1);
        reverseStr(s, n, s.size() - 1);
        reverseStr(s, 0, s.size() - 1);
        return s;
    }
};
  • 不额外开辟空间的话 能想到这个思路 的话 代码是很简单的 但关键是这个思路妙啊 不容易想到啊 》》》局部反转 然后整体反转
  • 卡哥代码用的reverse 要注意 一般系统编写好可直接调用的函数 常常是左闭右开原则 就是说 左端点值可以取到 右端点值不可以取到 所以要注意传参
    • 比如你要传的下标范围是 0到7(预期) 假设你代码写的是 reverse(0,7)
    • 拿去对照标准reverse(0,7)的话因为是左闭右开原则即意思是反转下标范围是0到6 (标准)
    • 标准不符合预期 那么你应该应该修改之前的reverse(0,7)为reverse(0,8) 才是正确的
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;
    }
};

【problems/0028.实现strStr】

class Solution {
public:
    int strStr(string haystack, string needle) {
        int result = -1;
        for (int i = 0; i <= haystack.size() - needle.size(); i++ ) {
            int count = 0;
            int j = 0;
            while (j < needle.size()) {
                if (haystack[i] == needle[j]) { 
                    i++;
                    count++;
                    j++;
                }
            }
            if (count == needle.size()) {
                result = i  - count;
                break;
            }

        }
        return result;
    }
};
  • 一些用例不通过 这其实就是暴力解法了
class Solution {
public:
    void getNext(int* next, const string& s) {
        int j = 0;
        next[0] = 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;
        }
    }
    int strStr(string haystack, string needle) {
        if (needle.size() == 0) {
            return 0;
        }
        int next[needle.size()];
        getNext(next, needle);
        int j = 0;
        for (int i = 0; i < haystack.size(); i++) {
            while(j > 0 && haystack[i] != needle[j]) {
                j = next[j - 1];
            }
            if (haystack[i] == needle[j]) {
                j++;
            }
            if (j == needle.size() ) {
                return (i - needle.size() + 1);
            }
        }
        return -1;
    }
};
  • 标准答案
    明天继续:)
posted @ 2022-11-14 21:24  跬步瑶  阅读(28)  评论(0)    收藏  举报