344.反转字符串
学习视频:字符串基础操作! | LeetCode:344.反转字符串_哔哩哔哩_bilibili
学习文档:代码随想录 (programmercarl.com)
学习时间:11:20-11:35
记录时间:11:50-12:10
状态:已听懂|可单独复写代码|暂不需复习
1. 看到问题后的初始想法 看完随想录后的迭代想法
第一次感受到自己算法能力实实在在的提升,要是换做以前的自己绝对想不到使用双指针法来解决哈哈哈哈哈哈。这题让我想到双指针法主要因为两点。第一点是题目要求我们在原本的数组上进行修改且空间复杂度不可以大于o(1),而双指针法恰恰就是在原数组上操作而不会占用过多的空间。第二点是因为字符串的反转可以将首尾的字符互换,然后再将次首位的字符互换,一直互换到左右两边重合,这就使我自然而然的想到了双指针法。
本题大概思路如下:设置left与right两个指针,将left初始化在0这个位置,right初始化在size-1的位置。只要left小于right,我们就互换left与right位置的元素,并使left右移一格,right左移一格。代码如下:
class Solution(object):
def reverseString(self, s):
"""
:type s: List[str]
:rtype: None Do not return anything, modify s in-place instead.
"""
size = len(s)
left = 0
right = size - 1
while left < right:
temp = s[left]
s[left] = s[right]
s[right] = temp
left += 1
right -= 1
return s
541. 反转字符串II
学习视频:字符串操作进阶! | LeetCode:541. 反转字符串II_哔哩哔哩_bilibili
学习文档:代码随想录 (programmercarl.com)
学习时间:12:10-12:45 14:45-15:00
记录时间:15:01-15:30
状态:已听懂|可单独复写代码|需复习简化代码的精髓
1. 看到问题后的初始想法
感觉没什么特别的技巧,应该是使用一个循环,这个循环是我们初始化一个节点start,然后每次循环都令start=2*k*i,i为循环的次数(没错,我的初始想法是先算出能够循环多少次),start为每次数组反转的起始点。我最初的想法是先求出要循环多少次,即len(s)//(2*k), 然后求余数remain,将remain与k进行比较从而采取不同的处理方式。这么写的话代码被分为两段段,第一段为start循环,然后在循环中处理前k个字符。第二段为判断remain是否小于k,若小于则反转,不小于则把前k个字符反转。下面为代码:
class Solution(object):
def reverseStr(self, s, k):
"""
:type s: str
:type k: int
:rtype: str
"""
def reverseString(s):
size = len(s)
s_list = []
for i in s:
s_list.append(i)
left = 0
right = size - 1
while left < right:
temp = s_list[left]
s_list[left] = s_list[right]
s_list[right] = temp
left += 1
right -= 1
s = ''
for string in s_list:
s = s + string
return s
size = len(s)
iteration = size // (2 * k)
remain = size - 2 *k * iteration
total = ''
for i in range(iteration):
start = i * 2 * k
end = (i + 1) * 2 * k
chunk = s[start+k:end]
chunk = reverseString(s[start:start+k]) + chunk
total = total + chunk
if remain < k:
total = total + reverseString(s[iteration*2*k:size])
else:
chunk = s[iteration*2*k+k:size]
chunk = reverseString(s[iteration*2*k:iteration*2*k+k]) + chunk
total = total + chunk
return total
2. 看完随想录后的迭代想法
这题还有一个更简洁的写法,我们不用算出具体需要迭代几次,只需要定义初始节点i=0,在while i < len(s)时每次增加2*k即可。然后在循环内,我们判断i+k是否小于等于字符串的长度,如果是的话就把前k个字符串反转(这个判断直接概括了题目中的两种情况,特别简洁!)然后如果i+k超过字符串长度的话,我们就把剩下的反转。但整体思想和我一开始想的差不多!(得意)
class Solution(object):
def reverseStr(self, s, k):
"""
:type s: str
:type k: int
:rtype: str
"""
i = 0
size = len(s)
while i < size:
if i + k <= size:
s = s[:i] + s[i:i+k][::-1] + s[i+k:]
else:
s = s[:i] + s[i:size][::-1]
i += 2 * k
return s
剑指Offer 05.替换空格
学习视频:谋
学习文档:代码随想录 (programmercarl.com)
学习时间:15:30-16:00
记录时间:16:00-16:14
状态:已听懂|leetcode题目被删了。。。|需复习简化代码的精髓
1. 看到问题后的初始想法
由于leetcode原题被删了,故我先做的leetcode的下位替代题(不是)。但是leetcode把‘%20’改成了'.'所以我直接用循环遍历找空格了了。。。后来看了下原题,想法也是先循环找空格,找到之后插入’%20‘.
class Solution(object):
def pathEncryption(self, path):
"""
:type path: str
:rtype: str
"""
path = list(path)
i, j = len(path) - 1, len(path) - 1
while i >= 0:
if path[i] != '.':
path[i] = path[j]
j -= 1
else:
path[j]
2. 看完随想录后的迭代想法
如果忽略python字符串不可变的特性的话或者直接把字符串编程list的话,这个思路确实值得我们学习。大概优化思路为:先将字符串(python中只可以拓展list)拓宽长度,每有一格空格就拓宽2格长度。然后设置两个指针,一个指针指向原列表的末尾(成为原指针),另一个指针指向新列表的末尾(成为新指针)。然后前后指针分别向前移动,若原指针不是空格,则新指针的值等于原指针的值,若原指针是空格,则新指针赋值’%20‘并向前进2格。当原指针与新指针重叠时,结束运行。
下面是代码随想录中的python代码:
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;
}
};
151.翻转字符串里的单词
学习视频:字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词_哔哩哔哩_bilibili
学习文档:代码随想录 (programmercarl.com)
学习时间:16:14-17:30
记录时间:17:31-19:00
状态:已听懂|跌跌撞撞复现代码(只报了2次错就ac了,意外)|需复习
1. 看到问题后的初始想法
第一次看这道题我想到了使用双指针法去空格,但由于没搞清楚slow指针加空格的特殊情况,遂作罢,直接看题。
2. 看完随想录后的迭代想法
费劲力气看完了解法,对于去除空格总算有了一个比较全面的了解。首先这题去除空格借鉴的是列表移除元素的双指针思想。而如果直接使用双指针去除空格的话会发现整个字符串中的空格都会被去除,因此我们需要在fast指针首次不是空格时给slow赋值空格,然后接下来再将fast的值传递给slow。具体怎么实现去重呢,看接下来的代码即可:
接下来就比较简单了,我们首先将整个string反转,再我们把string变成list后去重所有多余空格。接下来我们遍历list,当碰到空格或者遍历到最后一个字母时时将前面的单词 重新反转回来。
代码如下(做了我半个小时555):
class Solution(object):
def reverseWords(self, s):
"""
:type s: str
:rtype: str
"""
def reverseString(s):
size = len(s)
left = 0
right = size - 1
while left < right:
temp = s[left]
s[left] = s[right]
s[right] = temp
left += 1
right -= 1
return s
def removeSpace(s):
slow = 0
fast = 0
size = len(s)
while fast < size:
if s[fast] != ' ':
if slow != 0:
s[slow] = ' '
slow += 1
while fast < size and s[fast] != ' ':
s[slow] = s[fast]
slow += 1
fast += 1
else:
fast += 1
return s[0:slow]
s = list(s)
s = reverseString(s)
s = removeSpace(s)
size = len(s)
start = 0
for i in range(size):
if s[i] == ' ':
s[start:i] = reverseString(s[start:i])
start = i + 1
if i == size - 1:
s[start:i+1] = reverseString(s[start:i+1])
return ''.join(s)
剑指Offer58-II.左旋转字符串
学习视频:谋
学习文档:代码随想录 (programmercarl.com)
学习时间:18:00-18:19
记录时间:18:19-
状态:已听懂|由于python特性无法复现代码|暂不需复习
1. 看到问题后的初始想法
直接提取前target个字符串并把它们移动至最后,这个算法的时间、空间复杂度都是o(n)
class Solution(object):
def dynamicPassword(self, password, target):
"""
:type password: str
:type target: int
:rtype: str
"""
return password[target:] + password[:target]
2. 看完随想录后的迭代想法
如果使用的是C++,那就有空间复杂度为o(1)的算法。即先将前target个的元素反转,再将后面的元素反转,最后再将字符串整体反转即为所求。(以下代码为代码随想录中的代码,语言为C++)
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;
}
};