中国数据中心技术指针_使用两指针技术

中国数据中心技术指针

两指针技术 (The Two Pointer Technique)

The two-pointer technique is a near necessity in any software developer’s toolkit, especially when it comes to technical interviews. In this guide, we’ll cover the basics so that you know when and how to use this technique.

在任何软件开发人员的工具包中,尤其是涉及技术面试时, 两点技术都是必不可少的。 在本指南中,我们将介绍基础知识,以便您了解何时以及如何使用此技术。

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上 发布 ,我 那里维护技术面试课程,并为雄心勃勃的开发人员撰写思想著作。

模式是什么? (What is the pattern?)

The name two pointers does justice in this case, as it is exactly as it sounds. It's the use of two different pointers (usually to keep track of array or string indices) to solve a problem involving said indices with the benefit of saving time and space. See the below for the two pointers highlighted in yellow.

在这种情况下, two pointers的名称确实正确,因为听起来确实如此。 它使用两种不同的指针(通常是为了跟踪数组或字符串索引)来解决涉及所述索引的问题,从而节省了时间和空间。 请参阅下面的以黄色突出显示的两个指针。

But what are pointers? In computer science, a pointer is a reference to an object. In many programming languages, that object stores a memory address of another value located in computer memory, or in some cases, that of memory-mapped computer hardware.

但是pointers什么? 在计算机科学中, pointer是对对象的引用。 在许多编程语言中,该对象存储位于计算机内存中的另一个值的内存地址,或者在某些情况下存储内存映射的计算机硬件的地址。

Image for post

我们什么时候使用它? (When do we use it?)

In many problems involving collections such as arrays or lists, we have to analyze each element of the collection compared to its other elements.

在涉及集合(例如数组或列表)的许多问题中,我们必须分析集合中的每个元素与其他元素的比较。

There are many approaches to solving problems like these. For example we usually start from the first index and iterate through the data structure one or more times depending on how we implement our code.

有许多解决此类问题的方法。 例如,我们通常从第一个索引开始,然后根据实现代码的方式对data structure一次或多次迭代。

Sometimes we may even have to create an additional data structure depending on the problem's requirements. This approach might give us the correct result, but it likely won't give us the most space and time efficient result.

有时,我们甚至可能必须根据问题的要求创建其他data structure 。 这种方法可能会给我们正确的结果,但可能不会给我们带来最节省时间和空间的结果。

This is why the two-pointer technique is efficient. We are able to process two elements per loop instead of just one. Common patterns in the two-pointer approach entail:

这就是为什么two-pointer technique有效的原因。 每个循环我们可以处理两个元素,而不仅仅是一个。 两指针方法的常见模式包括:

  1. Two pointers, each starting from the beginning and the end until they both meet.

    两个指针,每个指针都从起点和终点开始,直到它们都相遇为止。
  2. One pointer moving at a slow pace, while the other pointer moves at twice the speed.

    一个指针以缓慢的速度移动,而另一个指针以两倍的速度移动。

These patterns can be used for string or array questions. They can also be streamlined and made more efficient by iterating through two parts of an object simultaneously. You can see this in the Two Sum problem or Reverse a String problems.

这些模式可用于字符串或数组问题。 通过同时遍历对象的两个部分,还可以简化它们并提高效率。 您可以在“ 两次和”问题或“ 反转字符串”问题中看到此问题。

通过一个例子 (Running through an example)

One usage is while searching for pairs in an array. Let us consider a practical example: assume that you have a sorted array arr.

一种用法是在数组中搜索对时。 让我们考虑一个实际的例子 :假设您有一个排序数组arr

You’re tasked with figuring out the pair of elements where arr[p] + arr[q] add up to a certain number. (To try this problem out, check the Two Sum and Sorted Two Sum problems here.)

您需要确定arr[p] + arr[q]为一定数量的一对元素。 (要尝试解决此问题,请在此处检查“ 两次和”和“ 两次 排序和”问题。)

The brute force solution is to compare each element with every other number, but that’s a time complexity of O(n^2). We can do better!

蛮力解决方案是将每个元素与其他每个元素进行比较,但这是O(n^2)的时间复杂度。 我们可以做得更好!

So let’s optimize. You need to identify the indices pointer_one and pointer_two whose values sum to the integer target.

因此,让我们进行优化。 您需要标识两个值的总和为整数target的指标指标pointer_onepointer_two

Let’s initialize two variables, pointer_one and pointer_two, and consider them as our two pointers.

让我们初始化两个变量, pointer_onepointer_two ,并将它们视为我们的两个指针。

pointer_one = 0
pointer_two = len(arr)-1

Note that len(arr)-1 helps to get the last index possible in an array.

请注意, len(arr)-1帮助获取数组中可能的最后一个索引。

Also observe that when we start, pointer_one points to the first element of the array, and pointer_two points to the last element.

还要注意,当我们开始时, pointer_one指向数组的第一个元素,而pointer_two指向最后一个元素。

This won’t always be the case with this technique (we’ll explore the sliding window concept later, which uses two pointers but have them move in a different direction). For our current purposes, it is more efficient to start wide, and iteratively narrow in (particularly if the array is sorted).

这种技术并非总是如此(稍后我们将探讨滑动窗口的概念 ,该概念使用两个指针,但使它们朝着不同的方向移动)。 就我们当前的目的而言,从宽处开始,以迭代方式变窄(尤其是对数组进行排序时),效率更高。

def two_sum(arr, target):
pointer_one = 0
pointer_two = input.length - 1while pointer_one < pointer_two:

Since the array is already sorted, and we’re looking to process an index at each iteration, we can use two pointers to process them faster. One pointer starts from the beginning of the array, and the other pointer begins from the end of the array, and then we add the values at these pointers.

由于数组已经排序,并且我们希望在每次迭代时处理索引,因此可以使用两个指针来更快地处理它们。 一个指针从数组的开头开始,另一个指针从数组的末尾开始 ,然后在这些指针处添加值。

Once we’re set up, what we want to do is check if the current pointers already sum up to our target. This might happen if the correct ones are on the exact opposite ends of the array.

设置好之后,我们要做的就是检查当前指针是否已经汇总到我们的目标上。 如果正确的数组位于数组的相对两端,则可能会发生这种情况。

Here’s what the check might look like:

这是支票的样子:

if sum == targetValue:
return true

However, it likely will not be the target immediately. Thus, we apply this logic: if the sum of the values is less than the target value, we increment the left pointer (move your left pointer pointer_one one index rightwards).

但是,它可能不会立即成为目标。 因此,我们采用以下逻辑:如果值的总和小于目标值,则增加左指针(向右移动左指针pointer_one一个索引)。

And if the sum is higher than the target value, we decrement the right pointer (correct the position of your pointer pointer_two if necessary).

如果总和高于目标值,我们将减少右指针(如有必要,请更正指针pointer_two的位置)。

elif sum < targetValue:
pointer_one += 1
else:
pointer_two -= 1

In other words, understand that if arr[pointer_one] < target-arr[pointer_two], it means we should move forward on pointer_one to get closer to where we want to be in magnitude.

换句话说,要理解,如果arr[pointer_one] < target-arr[pointer_two] ,则意味着我们应该继续前进pointer_one以接近我们想要达到的震级。

This is what it looks like all put together:

这是所有看起来像的东西:

def two_sum(arr, target):
pointer_one = 0
pointer_two = input.length - 1while pointer_one < pointer_two:
sum = input[pointer_one] + input[pointer_two]if sum == targetValue:
return true
elif sum < targetValue:
pointer_one += 1
else:
pointer_two -= 1return false

It’s crucial to see that how both indices were moving in conjunction, and how they depend on each other.

至关重要的是要看到两个索引如何一起移动,以及它们如何相互依赖。

We kept moving the pointers until we got the sum that matches the target value — or until we reached the middle of the array, and no combinations were found.

我们一直移动指针,直到获得与目标值匹配的总和-或直到到达数组的中间,并且没有找到任何组合。

The time complexity of this solution is O(n) and space complexity is O(1), a significant improvement over our first implementation!

该解决方案的时间复杂度为O(n) ,空间复杂度为O(1) ,这是对我们第一个实现的重大改进!

另一个例子 (Another Example)

In addition, to the previous example, the two pointer technique can also involve the pattern of using a fast pointer and a slow pointer.

另外,在前面的示例中,双指针技术还可以涉及使用快速指针和慢速指针的模式。

Node fast = head, slow = head

One usage is through detecting cycles in a linked list data structure. For example, a cycle (when a node points back to a previous node) begins at the last node of the linked list in the example below.

一种用法是通过检测linked list数据结构中的周期。 例如,在以下示例中,一个循环(当一个节点指向前一个节点时)开始于linked list的最后一个节点。

Image for post
1 -- > 2 --> 3 --> 4
^ |
| |
<- - -

The idea is to move the fast pointer twice as quickly as the slow pointer so the distance between them increases by 1 at each step.

想法是快速指针的移动速度是慢速指针的两倍,因此它们之间的距离在每一步增加1

Image for post
while(fast!=null && fast.next!=null){
slow = slow.next; fast = fast.next.next;

However, if at some point both pointers meet, then we have found a cycle in the linked list. Otherwise we’ll have have reached the end of the list and no cycle is present.

但是,如果某个时刻两个指针都相遇,则我们在链表中找到了一个循环。 否则,我们将到达列表的末尾,并且不存在任何循环。

Image for post

The attached code is what the entire method would look like all together.

所附代码就是整个方法的外观。

The time complexity would be O(N) or linear time.

时间复杂度为O(N)或线性时间。

Originally published at https://algodaily.com.

最初在 https://algodaily.com上 发布

翻译自: https://medium.com/swlh/using-the-two-pointer-technique-bf642ab05661

中国数据中心技术指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值