foreword
There is an array of integers, and we want to sort the elements in the array according to certain rules, such as: all odd numbers in the array are in the first half of the array.
This article will take you to implement this algorithm, and all interested developers are welcome to read this article.
Realize ideas
Let's analyze it through an example: Suppose there is such an array: [2, 4, 5, 6, 7, 8, 9, 11]
, move the odd number to the front, that is: [11, 9, 5, 7, 6, 8, 4, 2]
.
After observation, we found that when scanning this array, if we find that even numbers appear in front of odd numbers, we will exchange their order, and the exchange will meet the requirements.
Therefore, we can maintain two pointers:
- The first pointer is initialized to point to the first number of the array, it only moves backwards;
- The second pointer is initialized to point to the last number of the array, it only moves forward;
The first pointer is always in front of the second pointer until the two pointers meet. If the number pointed to by the first pointer is even and the number pointed to by the second pointer is odd, swap the two numbers.
Next, let's describe the process of exchanging pointers in the above example through a diagram, as follows:
- The first pointer always points to an even number, and moves backward if it is not even;
- The second pointer always points to an odd number, and moves forward if it is not odd;
- When the numbers pointed to by the two pointers meet the conditions, the positions of the two elements are exchanged;
- After the swap is complete, repeat the above steps until the two pointers meet or the first pointer is behind the second pointer, indicating that the problem has been solved.
implementation code
After we have an idea, let's take a look at the implementation code, as follows:
export class AdjustArrayOrder {
// 指向数组元素的两个指针:一个指向数组头部、一个指向数组尾部
private begin = 0;
private end = 0;
// 调整数组中奇数与偶数元素的位置:奇数位于偶数前面
reorderOddEven(arr: Array<number>): void {
this.end = arr.length - 1;
while (this.begin < this.end) {
// 向后移动begin(转成二进制跟1做与运算,运算结果为0就表示为偶数),直至其指向偶数
while (this.begin < this.end && (arr[this.begin] & 0x1) !== 0) {
this.begin++;
}
// 向前移动end(转成二进制跟1做与运算,运算结果为1就表示为奇数),直至其指向奇数
while (this.begin < this.end && (arr[this.end] & 0x1) === 0) {
this.end--;
}
// begin指向了偶数,end指向了奇数
if (this.begin < this.end) {
// 交换两个元素的顺序
[arr[this.begin], arr[this.end]] = [arr[this.end], arr[this.begin]];
}
}
// 重置指针位置
this.begin = 0;
this.end = 0;
}
}
Code Extensibility
If the elements in the array are not arranged according to odd, even after, we need to divide it according to size, all negative numbers are arranged in front of non-negative numbers, what should we do?
Smart developers may have come up with a solution: the idea of double pointers is still the same, we only need to modify the judgment conditions of the inner layer while
loop.
There is no problem with this answer, and it does solve the problem. Then if we change the title again, we need to divide the elements in the array into two parts. The numbers that are divisible by 3 are in front of the numbers that are not divisible by 3. What should we do?
After thinking about it, we found that no matter how the problem changes, there is one common part: the logic of double pointers will never change. The only thing that changes is the judgment condition, then we can extract the changed part into a function and pass it in as a parameter to the caller, which perfectly solves this problem, which is exactly the scalability of the code we mentioned.
Finally, let's look at the implementation code, as follows:
// 元素排序
reorder(arr: Array<number>, checkFun: (checkVal: number) => boolean): void {
this.end = arr.length - 1;
while (this.begin < this.end) {
// 向后移动begin
while (this.begin < this.end && !checkFun(arr[this.begin])) {
this.begin++;
}
// 向前移动end
while (this.begin < this.end && checkFun(arr[this.end])) {
this.end--;
}
// begin与end都指向了正确的位置
if (this.begin < this.end) {
// 交换两个元素的顺序
[arr[this.begin], arr[this.end]] = [arr[this.end], arr[this.begin]];
}
}
test case
Let's first test whether the function processing code with odd numbers before even numbers can be executed normally, as shown below:
const adjustArrayOrder = new AdjustArrayOrder();
// 奇数在前
const arr = [2, 4, 5, 6, 7, 8, 9, 11];
adjustArrayOrder.reorderOddEven(arr);
console.log(arr);
The execution result is as follows:
Finally, let's test whether the function reorder
can execute normally:
- Negative numbers are at the beginning of the array
// 负数在前
const checkMinusNumber = function (val: number) {
return val > 0;
};
const arr = [2, 4, 5, 6, 7, -8, -10 - 12, -2];
adjustArrayOrder.reorder(arr, checkMinusNumber);
console.log(arr);
- Numbers divisible by 3 are at the top of the array
const checkDivisible = function (val: number) {
return val % 3 !== 0;
};
const arr = [2, 4, 5, 6, 3, 6, 9, 12];
adjustArrayOrder.reorder(arr, checkDivisible);
console.log(arr);
sample code
For the full version of the code cited in the article, please move to:
write at the end
At this point, the article is shared.
I'm an amazing programmer , a front-end developer.
If you are interested in me, please visit my personal website to learn more.
- If there are any mistakes in the article, please correct them in the comment area. If this article helps you, please like and follow 😊
- This article was first published on the magical programmer's official account, and reprinting is prohibited without permission 💌
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。