字符串切片反转字符串
Can you write a function that reverses an inputted string without using the built-in Array#reverse
method?
您是否可以编写一个无需使用内置Array#reverse
方法即可反转输入字符串的函数?
Let’s look at some examples. So, calling:
让我们看一些例子。 因此,致电:
reverseString("jake")
should return "ekaj"
.
reverseString("jake")
应该返回"ekaj"
。
reverseString("reverseastring")
should return "gnirtsaesrever"
.
reverseString("reverseastring")
应该返回"gnirtsaesrever"
。
This lesson was originally published at https://algodaily.com, where I maintain a technical interview course and write think-pieces for ambitious developers.
本课程最初在 https://algodaily.com上 发布 ,我 在 那里维护技术面试课程,并为雄心勃勃的开发人员撰写思想著作。
对或错? (True or False?)
In Java, C#, JavaScript, Python and Go, strings are immutable
. This means the string object's state can't be changed after creation.
在Java,C#,JavaScript,Python和Go中,字符串是immutable
。 这意味着在创建后无法更改字符串对象的状态。
Solution: True
解决方案:正确
演示地址
采访者心态 (On Interviewer Mindset)
Reversing a string is one of the most common technical interview questions that candidates get. Interviewers love it because it’s deceptively simple. After all, as a software engineer, you’d probably call the #reverse
method on your favorite String
class and call it a day!
反转字符串是考生最常见的技术面试问题之一。 采访者喜欢它,因为它看似简单。 毕竟,作为一名软件工程师,您可能会在自己喜欢的String
类上调用#reverse
方法并每天调用它!
So don’t overlook this one — it appears a surprising amount as a warm-up or build-up question. Many interviewers will take the approach of using an easy question like this one, and actually judge much more harshly. You’ll want to make you sure really nail this.
因此,请不要忽视这一点-它似乎是一个令人惊讶的热身或堆积问题。 许多面试官会采用这样一个简单的问题,实际上会做出更严厉的判断。 您需要确保确实做到这一点。
我们将如何开始解决 (How We’ll Begin Solving)
We want the string reversed, which means that we end up with all our letters positioned backwards. If you need a quick review of string
s, check out our lesson on arrays and strings.
我们希望字符串反转 ,这意味着我们最终将所有字母都向后放置。 如果您需要快速查看 string
,请阅读 有关数组和string的课程 。
We know that string
s can be thought of as character arrays-- that is, each element in the array is a single character. And if we can assume that, then we know the location (array position) of each character, as well as the index when the array
ends.
我们知道string
s可以被认为是字符数组-也就是说,数组中的每个元素都是单个字符。 而且,如果可以假设,那么我们就知道每个字符的位置(数组位置)以及array
结束时的索引。
There’s a caveat to thinking of strings as character arrays — it’s not always true. As readers and viewers have pointed out, a string represents text formed from graphemes (the smallest functional unit of a writing system) — formed by combining character sequences in unicode.
需要将字符串视为字符数组,但并非总是如此。 正如读者和观众所指出的那样,字符串代表由字素(书写系统的最小功能单元)形成的文本,该字素是通过以Unicode组合字符序列而形成的。
Though strings and arrays contain similar methods like length
, concat
, and character position access-- they are not identical. As an example, arrays are mutable and strings usually are not. Before we can operate on the string as an array, we'll need to separate the units (in JS by calling the .split()
method, or bypass this property by generating a brand new string instead of trying to operate on the original.
尽管字符串和数组包含类似的方法,例如length
, concat
和字符位置访问- 但它们并不相同 。 例如,数组是可变的,而字符串通常不是可变的。 在将字符串作为数组进行操作之前,我们需要分隔单元(在JS中,通过调用.split()
方法,或通过生成全新的字符串来绕过此属性,而不是尝试对原始字符串进行操作)。
However, after the split
operation, we can apply that paradigm to operating on this string. Thus we can step through each of its indices. Stepping through the beginning of the string, we’ll make these observations at each point:
但是,在split
操作之后,我们可以将该范例应用于对该字符串的操作。 因此,我们可以逐步浏览其每个索引。 逐步浏览字符串的开头,我们将在每个点进行以下观察:
const str = "JAKE";
// position 0 - "J"
// position 1 - "A"
// ...
Since a reversed string is just itself backwards, a brute force solution could be to use the indices, and iterate from the back to the front.
由于反向字符串本身本身就是向后的,因此蛮力解决方案可能是使用索引,并从后向前迭代。
See the code attached and try to run it using Run Sample Code
. You'll see that we log out each character from the back of the string!
请参阅随附的代码,并尝试使用Run Sample Code
运行它。 您会看到我们从字符串的后面注销了每个字符!
function reverseString(str) {
let newString = '';
// start from end
for (let i = str.length-1; i >= 0; i--) {
console.log('Processing ', newString, str[i]);
// append it to the string builder
newString = newString + str[i];
}
// return the string
return newString;
}
console.log(reverseString('test'));
填写 (Fill In)
We want to console.log
out:
我们要console.log
注销:
5
4
3
2
1
What’s the missing line here?
这里缺少什么?
var arr = [1, 2, 3, 4, 5];
for (var i = ___________; i >= 0; i--) {
console.log(arr[i]);
}
Solution: arr.length — 1
解决方案: arr.length — 1
我们能比蛮力做得更好吗? (Can We Do Better Than Brute Force?)
However, it wouldn’t really be an interesting algorithms question if there wasn’t a better way. Let’s see how we can optimize this, or make it run faster. When trying to make something more efficient, it helps to think of things to cut or reduce.
但是,如果没有更好的方法,这实际上不是一个有趣的算法问题。 让我们看看如何优化它或使其运行更快。 当试图使某事更有效率时,考虑减少或减少的事情会有所帮助。
One thing to note is that we’re going through the entire string — do we truly need to iterate through every single letter?
需要注意的一件事是,我们要遍历整个字符串-我们是否真的需要遍历每个字母?
Let’s examine a worst case scenario. What if the string is a million characters long? That would be a million operations to work through! Can we improve it?
让我们研究一个最坏的情况。 如果字符串长度为一百万个字符怎么办? 这将需要进行一百万次操作! 我们可以改善吗?
是的,具有更多指针! (Yes, With More Pointers!)
Well, we’re only working with a single pointer right now. The iterator from our loop starts from the back, and appends each character to a new string, one by one. Having gone through The Two Pointer Technique, we may recognize that some dramatic improvements can be had by increasing the number of pointers we use.
好吧,我们现在仅使用单个指针。 循环中的迭代器从后面开始,并将每个字符一个接一个地追加到新字符串中。 经历了两次指针技术之后 ,我们可能会认识到,通过增加使用的指针数量,可以取得一些显着的改进。
By this I mean, we can cut the number of operations in half. How? What if we did some swapping instead? By using a while
loop and two pointers-- one on the left and one on the right.
我的意思是,我们可以将操作数量减少一半 。 怎么样? 如果我们进行一些交换该怎么办? 通过使用while
循环和两个指针-一个在左侧,一个在右侧。
With this in mind — the big reveal is that, at each iteration, we can swap the letters at the pointer indices. After swapping, we would increment the left
pointer while decrementing the right
one. That could be hard to visualize, so let's see a basic example listed out.
考虑到这一点,最大的启示是,在每次迭代中,我们都可以在指针索引处交换字母。 交换之后,我们将增加left
指针,同时减少right
指针。 这可能很难想象,所以让我们看一下列出的基本示例。
jake // starting string
eakj // first pass
^ ^
ekaj // second pass
^^
多项选择 (Multiple Choice)
What’s a good use case for the two pointers technique?
两个指针技术的一个好用例是什么?
- Shifting indices to be greater at each iteration 每次迭代的移位指数都更大
- Reducing a solution with a nested for-loop and O(n²) complexity to O(n) 将嵌套循环和O(n²)复杂度降低为O(n)的解决方案
- Finding pairs and duplicates in a for-loop 在for循环中查找对和重复项
- None of these 都不是
Solution: Reducing a solution with a nested for-loop and O(n²) complexity to O(n)
解决方案:将嵌套的for循环和O(n²)复杂度的解决方案简化为O(n)
With two pointers, we’ve cut the number of operations in half. It’s much faster now! However, similar to the brute force, the time complexity is still O(n)
.
使用两个指针,我们将操作数减少了一半。 现在要快得多! 但是,类似于蛮力,时间复杂度仍然是O(n)
。
为什么是这样? (Why Is This?)
Well, if n
is the length of the string, we'll end up making n/2
swaps. But remember, Big O Notation isn't about the raw number of operations required for an algorithm-- it's about how the number scales with the input.
好吧,如果n
是字符串的长度,我们最终将进行n/2
交换。 但是请记住, Big O表示法与算法所需的原始操作数无关,而是与输入数如何缩放有关 。
So despite requiring half the number operations — a 4
-character string would require 2
swaps with the two-pointer method. But an 8
-character string would require 4
swaps. The input doubled, and so did the number of operations.
因此,尽管只需要执行一半的数字运算,但一个4
字符的字符串将需要使用两指针方法进行2
交换。 但是8
字符的字符串将需要进行4
交换。 输入增加了一倍,操作数也增加了。
最终解决方案 (Final Solution)
function reverseString(str) {
let strArr = str.split("");
let start = 0;
let end = str.length - 1; while (start <= end) {
const temp = strArr[start];
strArr[start] = strArr[end];
strArr[end] = temp;
start++;
end--;
} return strArr.join("");
}
Originally published at https://algodaily.com on August 19, 2020.
最初于 2020年8月19日 发布在 https://algodaily.com 上。
翻译自: https://medium.com/swlh/how-to-reverse-a-string-16a2acc1dab8
字符串切片反转字符串