1. Background
I recently came across an algorithm problem: find a number that appears only once in an array.
The title description is this:
Given a non-empty array of integers, each element appears twice except one that appears only once. Find the element that appears only once
Explanation: Your algorithm should have linear time complexity. Can you do it without using extra space ?
Example:
Input: [4, 1, 2, 2, 1]
output: 4
Without reading the description, the smart mind immediately thought of using the object to store the number that has appeared in the array, and then the number appears again delete
the number, and finally there is only one number left in the object. This is also one of the ways to solve problems with violence.
Talk is cheap, Show me your code:
/**
* @param {number[]} nums
* @return {number}
*/
const singleNumber = function(nums) {
const result = {};
for (let i = 0; i < nums.length; i++) {
if (result[nums[i]] === undefined) {
result[nums[i]] = nums[i];
} else {
delete result[nums[i]];
}
}
return Object.values(result)[0];
};
The problem is solved, but the performance is mediocre:
On second thought, the quickest way, without using extra space, is to sort the array first, and then compare adjacent numbers for equality . Is it a clever one, and quickly put the code:
/**
* @param {number[]} nums
* @return {number}
*/
const singleNumber = function(nums) {
const newNums = nums.sort();
let num = newNums[0];
if (newNums.length === 1) {
return num;
}
for(let i = 0; i < newNums.length; i++) {
if (newNums[i] !== newNums[i + 1]) {
if (i === 0) {
num = newNums[0];
break;
}
// 可前置判断是否数组越界
// if (i + 3 > newNums.length) {
// num = newNums[i + 1];
// break;
// }
if (newNums[i + 1] !== newNums[i + 2]) {
num = newNums[i + 1];
break;
}
}
}
return num;
};
As expected, the problem is solved and the performance is improved:
Do you suddenly feel that you can do it again! !
Just when I thought I could hand in my homework in this way, I looked at other students' problem-solving ideas, and I realized that I am really smart. There is a mathematical operator that solves every second: XOR
Code first:
/**
* @param {number[]} nums
* @return {number}
*/
const singleNumber = function(nums) {
return nums.reduce((a, b) => a ^ b, 0);
};
You read that right, just one line of code! ! ! ! More amazing is yet to come, let's see how the performance is:
Sure enough, the lack of knowledge limits my imagination. Of course, there are more powerful problem-solving methods. You are also welcome to communicate in the comment area. Then I will introduce the XOR operation to you.
2. Introduction
The logical operations that everyone is familiar with are mainly "AND" ( AND
) and "OR" ( OR
), and there is also an "XOR" ( XOR
) is also very important.
XOR
is the abbreviation of exclusive OR
, which is mainly used to judge whether two values are equal.
XOR
Generally use the caret ( caret
) ^
to indicate. If 0 is false
and 1 is true
, then the truth table of XOR
is as follows:
0 ^ 0 = 0;
0 ^ 1 = 1;
1 ^ 0 = 1;
1 ^ 1 = 0;
2.1 The Law of Operation
A value and itself, always
false
x ^ x = 0;
A value is computed with
0
, which is always itselfx ^ 0 = x;
interchangeability
x ^ y = y ^ x;
associative
x ^ (y ^ z) = (x ^ y) ^ z;
3. Application
According to the above operation laws, many important applications of XOR operation can be obtained.
3.1 Simplified operations
The XOR operation of multiple values can be simplified according to the operation law:
a ^ b ^ c ^ a ^ b
= a ^ a ^ b ^ b ^ c
= 0 ^ 0 ^ c
= c
3.2 Interaction value
Two variables are XORed three times in a row, and they can exchange values with each other.
let a = 1;
let b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;
console.log(`a: ${a}, b: ${b}`); // a: 2, b: 1
This is the fastest way to swap values between two variables and doesn't require any extra space. It is also the key to solving the problem at the beginning to find the number that only appears once in the array.
3.3 Encryption
XOR operation can be used for encryption.
The first step, plaintext: text
and key: key
XOR operation, you can get ciphertext: cipherText
text ^ key = cipherText;
In the second step, the ciphertext and the key are XORed again to restore the plaintext
cipherText ^ key = text
The principle is very simple, if the plaintext is x
and the key is y
, then x
consecutively OR with y
twice in a row get yourself.
(x ^ y) ^ y
= x ^ (y ^ y)
= x ^ 0
= x
3.4 Data Backup
XOR operation can be used for data backup.
The file x
and the file y
are XORed to produce a backup file.
x ^ y = z
Later, whether file x or file y is damaged, as long as the two original files are not damaged at the same time, the restoration can be performed based on the other file and the backup file.
x ^ z
= x ^ (x ^ y)
= (x ^ x) ^ y
= 0 ^ y
= y
The above example is y
corrupt, x
and z
XOR, you can get y
.
4. Conclusion
If a worker wants to do a good job, he must first sharpen his tools. Only by constantly improving your own knowledge system can you discover a different world, respect! !
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。