preface
First of all, it is an algorithm for the interview questions, questions mainly hot 100 | tencent in leetcode selected 50 | select Top interview questions | sword refers to offer | interview questions encountered in some algorithm, the full 122, basic covers the front end of the interview topic classification algorithm. Because of personal ability is limited, so the title is almost easy | mids, and answer the following questions are handling some of the best in the references. If it helps, go to 👍 and collect ❤️
directory
- dp
- greedy
- binary
- back
- The sorting
- Check and set
- A topological sort
- An operation
- Double pointer
- matrix
- Binary tree
- Hash table
- The stack and queue
- The list
- string
dp
thought
It’s kind of like the idea of a sequence in high school, where you’re given the first term, and you’re given a recursive formula, and you’re asked to evaluate any term.
The basic steps are: find the state transition equation => create the appropriate data structure table => fill in the table
Climb the stairs
Suppose you are climbing the stairs. It takes you n steps to get to the top.
You can climb one or two steps at a time. How many different ways can you climb to the top of the building
dp[0] = 0 dp[1] = 1 dp[2] = 2
dp[n] = dp[n- 1] + dp[n2 -] // There are two ways to get to the NTH stair: one step from the n-1 step and two steps from the n-2 step
var climbStairs = function(n) {
let dp = [];
dp[0] = 0,dp[1] = 1,dp[2] = 2;
for(let i = 3; i <= n; i++){ dp[i] = dp[i2 -] + dp[i- 1];
}
return dp[n];
};
Copy the code
Al shabaab
You are a professional thief, planning to steal houses along the street. Each house has a certain amount of cash hidden in it, and the only restriction that affects your theft is that the adjacent houses are connected to the anti-theft system. If two adjacent houses are broken into on the same night, the system will automatically alarm.
Given an array of non-negative integers representing the amount of money stored in each house, calculate the maximum amount you can steal without activating the alarm
Dp [n] = num + Max(dp[n-1])
/ / not can in neighbouring houses into, so in the current position n house can be a maximum of theft, or house can be a maximum of theft, n - 1 or n - 2 house can be a maximum of theft and the current value of homes between maximum value
// For example: The maximum value of room 1 is 33, that is, dp[1]=3. The maximum value of room 2 is 44, that is, DP [2]=4. The value of room 3 itself is 22, that is, num=2. Then dp[3] = MAX(dp[2], dp[1] + num) = MAX(4, 3+2) = 5
var rob = function(nums) {
if(nums.length === 0) return 0;
if(nums.length === 1) return nums[0];
if(nums.length === 2) return Math.max(nums[0],nums[1]);
let dp = [nums[0].Math.max(nums[0],nums[1])];
for(let i = 2; i < nums.length; i++){ dp[i] =Math.max(dp[i- 1],dp[i2 -]+nums[i]);
}
return Math.max(dp[nums.length- 1],dp[nums.length2 -]);
};
Copy the code
Maximum square
In a two-dimensional matrix of 0s and 1s, find the largest square containing only 1s and return its area
const maximalSquare = (matrix) = > {
if(! matrix.length)return 0
let maxsqlen = 0
let rowLength = matrix.length, colLength = matrix[0].length
for (let row = 0; row < rowLength; row++) {
for (let col = 0; col < colLength; col++) {
if (matrix[row][col] === '1') {
matrix[row][col] = Number(matrix[row][col])
if(row ! =0&& col ! =0) {
matrix[row][col] = Math.min(matrix[row- 1][col], matrix[row- 1][col- 1], matrix[row][col- 1]) + 1
}
maxsqlen = Math.max(maxsqlen, matrix[row][col])
}
}
}
return maxsqlen**2
}
DP / * * * the topic request big square area, area = * side length, which is for big square side length * also becomes so, find the largest square in the matrix, the matrix of the only two values 0 | 1, all of 1 is a square * how do you know where the matrix is 1, where is 0, can only be exhaustive, But do it wisely, and that's what dynamic programming is all about. The first step of dynamic programming is to create a two-dimensional array dp, which is used to store "this point is the side length of the largest square in the lower right corner". Suppose we have the following matrix * 1 0 1 1 1 * 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 * 1 1 1 1 1 1 * 1 0 0 1 1 * 1 1 * 1 0 0 1 1 * 1 0 0 1 1 * 1 0 0 1 1 * 1, let's find the point in the bottom right first, let's find the maximum square side length of this point dp[I][J], let's see with the naked eye, Dp [I] [j] why should be equal to 2 * equals 2, because we see the dp [j], [I - 1] dp [I - 1] [1], dp [I] [1] this three points to 1, and because the dp [I] [2] j - 0, so we know * dp [I] [j] maximum of 2. In other words, we should not only look at the three adjacent points dp[I][j], but also look at the side length of "these three adjacent points are the lower right corner of the square". * Take the minimum side length to solve the maximum square side length of dp[I][j]. (Look, we find the overlapping subproblem and the optimal substructure) * Therefore, the state transition equation is: Dp [I] [j] = math.h min (dp [j], [I - 1] dp [I - 1] [1], dp [I]] [j - 1) + 1 * next, need according to the data matrix, to select and clear the base case. * /
Copy the code
Change change
Give coins of different denominations and a total amount. Write a function to calculate the minimum number of coins needed to make up the total amount. If none of the coin combinations make up the total amount, -1 is returned
// dp[0] = 0 no coin is required when the amount is zero
/ / dp [n] = min (dp [n], dp - coin1] [n + 1, dp [n - coin2],...). For an amount of n, the number of coins is equal to the combination of (n-coins)+1 with the fewest coins required
var coinChange = function(coins, amount) {
let dp = new Array( amount + 1 ).fill( Infinity );
dp[0] = 0;
for (let i = 1; i <= amount; i++) {
for (let coin of coins) {
if (i - coin >= 0) {
dp[i] = Math.min(dp[i], dp[i - coin] + 1); }}}return dp[amount] === Infinity ? - 1 : dp[amount];
}
Copy the code
Different paths
A robot is located in the upper left corner of an m x N grid (the starting point is marked “Start” in the image below).
The robot can only move one step down or to the right at a time. The robot tries to reach the lower right corner of the grid (marked “Finish” in the image below).
How many different paths are there altogether
var uniquePaths = function(m, n) {
if(m === 1 && n === 1) return 1;
let data = [],rows = [0];
for(let i = 0; i < n- 1; i++){ rows.push(1);
}
data.push(rows);
for(let i = 0; i < m- 1; i++){ data.push([1]);
}
for(let i = 1; i < m; i++){for(let j = 1; j < n; j++){ data[i][j] = data[i- 1][j] + data[i][j- 1]; }}return data[m- 1][n- 1];
};
Copy the code
Stock problem state machine
This article will tell you the framework, and then take you a second to kill.
These 6 stock trading problems are common, and we will solve them one by one through the analysis of the fourth problem (limit the maximum number of transactions to K). Because the fourth problem is the most general form, all the other problems are simplifications of this form.
The first is to make only one transaction, which is equal to k = 1; K = +infinity (k = +infinity) The third is that you only make two trades, which is equal to k = 2; The remaining two questions are also unlimited, but with the additional conditions of “freezing period” and “handling fee”, they are actually variants of the second question and are easy to handle.
One, exhaustive frame
First, the same idea: How to bruise? The exhaustive idea here is not quite the same as the recursive idea in the previous article.
Recursion is actually in line with the logic of our thinking, step by step, encounter can not solve to throw to recursion, accidentally made, readability is very good. The downside is that when something goes wrong, it’s hard to figure out why it happened. The recursive solution in the last article, for example, is certainly computatively redundant, but it’s not easy to find.
Here, instead of exhausting with recursion, we’re exhausting with states. Let’s look at each day, see how many possible “states” there are, and find the “choices” for each “state.” We want to exhaustive all the “states”, the purpose of exhaustive is to update the state based on the corresponding “selection”. It sounds abstract, but all you have to do is memorize the words “state” and “choice.” It’s easy to understand when you practice it.
forState 1inAll values of status 1:forState 2inAll values of status 2:for. Dp [State 1][State 2][... = Preferred (choose 1, choose 2...)Copy the code
For example, there are three “options” every day: buy, sell, and do nothing. We use buy, sell, and rest for these three options. But the problem is that you can’t choose any of these three options every day, because sell must come after buy, and buy must come after sell. Then the REST operation should have two states, one is REST after buy (holding the stock), and the other is REST after sell (holding no stock). And don’t forget, we also have a limit on the number of transactions k, which means you can only buy if k is greater than 0.
Very complex right, don’t be afraid, our purpose now is just exhaustive, you have more states, the old man to do is a shuttle all list out. The first is the number of days, the second is the maximum number of transactions allowed, and the third is the current hold state. We can then use a three-dimensional array to hold all the combinations of these states:
Dp [I][k][0 or 1] 0 <= I <= n-1, 1 <= k <= k, n = number of days, k = maximum number of transactionsfor 0 <= i < n:
for 1 <= k <= K:
for s in {0, 1}:
dp[i][k][s] = max(buy, sell, rest)
Copy the code
And we can describe the meaning of each state in natural language. For example, DP [3][2][1] means: Today is the third day, I am holding the stock now, and I have made at most 2 trades so far. Dp [2][3][0] : Today is the second day, I have no stock in hand now, so far the most 3 trades. Easy to understand, right?
The final answer we want to find is dp[n-1][K][0], that is, on the last day, the maximum number of transactions allowed, the maximum number of profits. The reader may ask why not dp[n-1][K][1]? Because [1] means that the shares are still held, and [0] means that the shares have been sold, it is obvious that the latter must get a greater profit than the former.
Remember how to interpret “state”, and once you find something difficult to understand, translate it into natural language.
Second, the state transition framework
Now that we’ve exhausted our “states,” we start thinking about what “options” are available for each “state” and how we should update the “states.” Just looking at the holding state, you can draw a state transition diagram.
It is clear from this diagram how each state (0 and 1) is transferred. Based on this graph, let’s write the state transition equation:
Dp [I][k][0] = Max (dp[i-1][k][0], dp[i-1][k][1] + prices[I]) Max (select rest, select sell) Either I didn't have it yesterday, and I chose REST today, so I still don't have it today; Either I owned the stock yesterday, but I sold today, so I don't own the stock today. Dp [I][k][1] = Max (dp[i-1][k][1], dp[i-1][k-1][0] -prices [I]) Max (select rest, select buy) Either I owned the stock yesterday and I chose REST today, so I still own the stock today; Either I didn't own it yesterday, but I bought it today, so I own the stock today.Copy the code
If we buy, we will subtract prices[I] from the profit. If we sell, we will increase prices[I] from the profit. The biggest profit today is the larger of the two possible options. And notice the limitation of k, we reduced k by 1 when we said buy, which makes sense, and of course you can subtract 1 when you say sell, same thing.
We have now completed the most difficult step in dynamic programming: the state transition equation. If you understand the previous content, then you can kill all the problems in a second, just use this framework. But the last thing we need is to define the base case, the simplest case.
If you are allowed to complete at most one trade (that is, buy and sell a stock once), design an algorithm to calculate the maximum profit you can make.
var maxProfit = function(prices) {
let dp_i_0 = 0,dp_i_1 = -Infinity;
for(let i = 0; i < prices.length; i++){ dp_i_0 =Math.max(dp_i_0,dp_i_1+prices[i]);
dp_i_1 = Math.max(dp_i_1,-prices[i]);
}
return dp_i_0;
};
Copy the code
The best time to buy and sell stocks II
1.As long as the stock price goes up, the part that goes up is my profit, which can be interpreted as buying on the first day of the rise and then holding on until the last day of the rise, the day before the fall2.Whenever the price of a stock goes down, I always sell it the day before it goes down, and I never buy it while it's downvar maxProfit = function(prices) {
let profit = 0;
for (let i = 0; i < prices.length - 1; i++) {
if (prices[i + 1] > prices[i]) profit += prices[i + 1] - prices[i];
}
return profit;
};
Copy the code
greedy
thought
When solving a problem, always make the best choice at the moment. In other words, instead of thinking in terms of global optimality, what he did was in a sense the local optimality the local optimality
Cut the rope
Give you a piece of string of length N, please cut the string into m segments of integer length (m and n are integers, n>1 and m>1), the length of each segment of string is denoted by k[0],k[1]… K [m]. Excuse me [1] [0] k k… What is the largest possible product of *k[m]? For example, if the length of a string is 8 and we cut it to lengths of 2, 3, and 3, the maximum product we get is 18.
var cuttingRope = function(number) {
if(number === 2 || number === 3) return number - 1;
let a = number % 3;
let b = parseInt(number / 3);
if(a === 0) {return 3 ** b;
}else if(a === 1) {return 2 * 2 * (3 ** (b - 1));
}else{
return 2 * (3** b); }};Copy the code
Jumping games
Given an array of non-negative integers, you start at the first position in the array.
Each element in the array represents the maximum length you can jump at that position.
Determine if you can reach the last position.
1.Use a variable to hold the current maximum reachable position2.Update the maximum position at all times3.Reachable position less than the array lengthfalseAnd vice versavar canJump = function(nums) {
let k = 0;
for(let i = 0; i < nums.length; i++){if(i > k) return false;
k = Math.max(k,i + nums[i]);
}
return true;
};
Copy the code
Gas station
There are N gas stations on a ring road, of which the ith station has gas[I] liters.
If you have a car with unlimited gas tank capacity, it costs cost[I] liters of gasoline to go from station I to station I +1. You start at one of the gas stations with an empty tank.
If you can drive around the loop once, return to the station number where you started, otherwise return -1
1. gas - cost >= 0So you can go around the field, and you can use that thought to see if you can go around the field2.You start at the right starting position, you always have more gasoline than you consume, and you find your starting position with that ideavar canCompleteCircuit = function(gas, cost) {
let cur = 0,total = 0,start = 0;
for(let i = 0; i < gas.length; i++){ total += gas[i] - cost[i];if(cur < 0){
cur = gas[i] - cost[i];
start = i;
}else cur += gas[i] - cost[i];
}
return total >= 0 ? start : - 1;
};
Copy the code
binary
thought
When searching for ordered sequence, dichotomy is preferred
Input a rotation of a non-decrement sorted array, and output a rotation of the smallest element of the array
// for example, the array {3,4,5,1,2} is a rotation of {1,2,3,4,5}. The minimum value of the array is 1.
// return 0 if the size of the array is 0.
// Moving the first elements of an array to the end of the array is called array rotation.
/ / 10111
1.The original data is a rotated array, so it is ordered before and after the cut-off point2.We're going to do a binary search, and notice that because we're looking for the minimum, we're going to start with mid when we assign high, and mid might be the minimumfunction minNumberInRotateArray(rotateArray)
{
if(! rotateArray.length)return 0;
let left = 0,right = rotateArray.length- 1;
while(left < right){
let mid = Math.floor((right+left) >> 1);
if(rotateArray[left] <= rotateArray[right]){
return rotateArray[left];
}
if(rotateArray[left] < rotateArray[mid]){
left = mid + 1;
}else if(rotateArray[right] > rotateArray[mid]){
right = mid;
}else{ left++; }}}Copy the code
Counts the number of times a number appears in a sorted array
function GetNumberOfK(data, k)
{
let low = 0,high = data.length- 1;
let pos,count = 0;
while(low < high){
let mid = Math.floor((low+high)>>1);
if(data[mid] === k){
pos = mid;
break;
}else if(data[mid] < k){
low = mid + 1;
}else{
high = mid- 1; }}if(pos ! = =undefined){
count++;
let left = pos,right = pos;
while(left--){
if(data[left] === k){
count++;
}else{
break; }}while(right++){
if(data[right] === k){
count++;
}else{
break; }}return count;
}else return 0;
}
Copy the code
The missing numbers from 0 to n-1
All numbers in an incrementing sorted array of length n-1 are unique, and each number is in the range 0 to n-1. If only one of the n numbers in the range 0 to n-1 is not in the array, find this number
var missingNumber = function(nums) {
let left = 0,
right = nums.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (mid === nums[mid]) {
left = mid + 1;
} else if (mid < nums[mid]) {
right = mid - 1; }}return left;
};
Copy the code
Longest ascending subsequence
1.Maintains a subsequence to hold the current ascending sequence2.Compare the current number with the maximum value of the subsequence, add the end of the queue if larger than the maximum value, and replace the element at the current position if updatedvar lengthOfLIS = function(nums) {
let n = nums.length;
if(n <= 1) {return n;
}
let tail = [nums[0]].for(let i = 0; i < n; i++){if(nums[i] > tail[tail.length- 1]){
tail.push(nums[i]);
}else{
let left = 0;
let right = tail.length- 1;
while(left < right){
let mid = (left + right) >> 1;
if(tail[mid] < nums[i]){
left = mid + 1;
}else{ right = mid; } } tail[left] = nums[i]; }}return tail.length;
};
Copy the code
Search for the two-dimensional matrix II
Write an efficient algorithm to search for a target value in the m x n matrix matrix. The matrix has the following properties:
The elements in each row are arranged in ascending order from left to right. The elements of each column are arranged in ascending order from top to bottom.
Enter such a two-dimensional array and an integer and determine whether the array contains the integer.1.Select the value in the lower left corner as the initial key2.If the target value is greater than the key, because it is the leftmost value (minimum), so col++3.If the target value is less than, then the only smaller value can be the previous row, so row--function Find(target,array){
let rows = array.length;
if(rows <= 0) return false;
let cols = array[0].length;
if(cols <= 0) return false;
let row = rows - 1;
let col = 0;
while(row >= 0 && col < cols){
if(array[row][col] > target){
row--;
}else if(array[row][col] < target){
col++;
}else{
return true; }}return false;
}
Copy the code
Pow(x, n)
Implement POw (x, n), that is, calculate x to the n power function
// Fast power algorithm
var myPow = function(x, n) {
if(! x)return 0;
if (x === 1) return 1;
if (x === - 1) return (n & 1)?- 1 : 1;
if (n == 2147483647) return 0;
if (n == - 2147483648.) return x === 2 ? 0 : 1;
if (n < 0) {
x = 1 / x;
n = -n;
}
let res = 1;
while(n) {
if (n & 1) res *= x;
x *= x;
n >>= 1;
}
return res;
}
Copy the code
masked
function intersection(. args){
if(! args.length)return [];
let res = [],left = args[0] [0],right = args[0] [1];
for(let i = 1; i < args.length; i++){if(right >= args[i][0] || left <= args[i][1]){
left = Math.max(left,args[i][0]);
right = Math.min(right,args[i][1]);
res = [left,right];
}else{
return[]; }}return res;
}
Copy the code
Backtracking algorithm
Their thinking
-
Global variables: Save results
-
Argument: The choice of arguments, usually two, for a recursive function.
- Status variable: result specifies the value to be saved
- Condition variable: determines whether the search is complete and whether the search is valid
-
Completion condition: The completion condition determines the value of the state and condition variables to determine the end of the search process. The end of the search process has two meanings: the search succeeds and the results are saved, and the search fails and the last status is returned.
-
Recursive procedure: pass the current state to the next recursive search.
The template
let res = []; // Store the result
function backtrack(path,condition,...){
if(judge(condition)){ // Satisfy the conditions
res.push(path);
return;
}
for(let select of selectList){
if(Pruning condition)break;
path.push(select); // Go a certain way
backtrack(path,newSelectList);
path.pop(); // Return to the previous intersection}}Copy the code
Applicable scenario
- Permutation, combination
- Array, string, given a particular rule, trying to find some solution
- DFS search under a two-dimensional array
How to apply the template
I have screened the questions about backtracking in hot and interview Quiz in leetCode, and the questions are from easy to difficult, covering each usage scenario.
A subset of
Given a set of integer array NUMs with no repeating elements, return all possible subsets (power sets) of that array.
- Define an RES array to store results
- Each subset is a state variable, and the number of elements in the set is a condition variable
- The number of elements in the subset is less than or equal to the number of elements in the collection. If the number of elements in the subset is less than or equal to the number of elements in the collection, it is added to the result array. Otherwise, it goes back to the previous step
- The collection searched at the next level needs to remove elements that have been added to the state variable
var subsets = function(nums) {
let res = [];
let n = nums.length;
function back(path,i){
if(i <= n){
res.push(path);
}
for(letj = i; j < n; j++){ path.push(nums[j]); back(path.slice(0),j+1);
path.pop();
}
}
back([],0);
return res;
};
Copy the code
There’s another cool way to do this, which is to use binary
-
The second to the NTH subset of a set
-
Using binary simulation, each is fetched or not fetched
-
For example: [1,2,3] => sign bit: 001 010 100 => 0-7 with &
=> [] [001] [010] [001,010] [100] [001,100] [010,100] [001,010,100] [001,010,100] Exactly eight types, which correspond to array subscripts.
var subsets = function(nums) {
let n = 1 << nums.length;
let res = [];
for(let i = 0; i < n; i++){let temp = [];
for(let j = 0; j < nums.length; j++){if(i & (1 << j)){
temp.push(nums[j]);
}
}
res.push(temp);
}
return res;
};
Copy the code
The whole arrangement
Given a sequence with no repeating numbers, return all possible permutations.
- Define the res
- Each permutation sequence is a state variable, and the number of sets in the permutation sequence is a condition variable
- The condition is satisfied when the number of elements in the permutation sequence is equal to the given sequence
- The next level of recursion depends on the path passed by the previous level of recursion
var permute = function(nums) {
let len = nums.length;
let res = [];
function back(path){
if(path.length === len){
res.push(path);
return;
}
for(let i = 0; i < len; i++){if(path.indexOf(nums[i]) === - 1) {// This is a very good judgment
path.push(nums[i]);
back(path.slice());
path.pop();
}
}
}
back([]);
return res;
};
Copy the code
Combined total
Given an array of candidates with no duplicate elements and a target, find all the combinations in the candidates that can make the sum of the digits as target. The numbers in the candidates may be selected indefinitely.
- Define the res
- Each subarray is a state variable and the target value is a condition variable
- If the values in the subarray add up to the target value
- The tar (the number of deviations from the target value) of the next recursive level depends on the selection of the previous recursive level
var combinationSum = function(candidates, target) {
let res = [];
let len = candidates.length;
// this is to prevent the for loop from jumping out of the if judgment, such as the example [8,7,4,3],11
candidates.sort((x,y) = > x-y);
function back(path,i,tar){
if(tar === 0){
res.push(path);
return;
}
for(letj = i; j < len; j++){// Determine whether the current intersection is leading to a dead end
if(tar < candidates[j]) break;
path.push(candidates[j]);
back(path.slice(),j,tar-candidates[j]);
path.pop();
}
}
back([],0,target);
return res;
};
Copy the code
Split palindrome strings
Given a string s, divide S into substrings such that each substring is a palindrome.
Returns all possible split options for S.
- Define the res
- The state variable is the return substring set, and the condition variable is the number of strings in the substring set
- When the number of strings in the substring set is the same as the length of the target string, the requirement is met
- The starting position of the lower recursion is determined by the upper recursion
var partition = function(str){
let res = [];
function isPalindrome(s){
let head = 0;
let tail = s.length- 1;
while(head <= tail){
if(s[head] ! == s[tail])return false;
head++;
tail--;
}
return true;
}
function backtrack(path,start){
if(start === str.length) res.push(path);
for(leti = start; i < str.length; i++){if(! isPalindrome(str.slice(start,i+1))) continue;
path.push(str.slice(start,i+1));
backtrack(path.slice(),i+1);
path.pop();
}
}
backtrack([],0);
return res;
}
Copy the code
Word search
Given a two-dimensional grid and a word, find out if the word exists in the grid.
Words must be formed in alphabetical order by letters in adjacent cells, where “adjacent” cells are those that are contiguous horizontally or vertically. Letters in the same cell are not allowed to be reused.
- The state variable is a path, and the condition variable is the length of the path
- When the path is the same length as the target word, the condition is met
- The initial coordinates and path length of the next recursive level are determined by the upper recursive level
var exist = function (board, word) {
// Crossing the border
board[- 1] = []
board.push([])
// Look for the first letter
for (let y = 0; y < board.length; y++) {
for (let x = 0; x < board.length; x++) {
if (word[0] === board[y][x] && backtrack(y, x, 0)) return true}}/ / back
function backtrack(y, x, i) {
// Traceback termination
if (i + 1 === word.length) return true
// Save the letter
var tmp = board[y][x]
board[y][x] = false
if (board[y][x + 1] === word[i + 1] && backtrack(y, x + 1, i + 1)) return true
if (board[y][x - 1] === word[i + 1] && backtrack(y, x - 1, i + 1)) return true
if (board[y + 1][x] === word[i + 1] && backtrack(y + 1, x, i + 1)) return true
if (board[y - 1][x] === word[i + 1] && backtrack(y - 1, x, i + 1)) return true
// Restore letters
board[y][x] = tmp
}
return false
};
Copy the code
Restoring the IP Address
Given a string containing only numbers, undo it and return all possible IP address formats.
A valid IP address consists of exactly four integers (each between 0 and 255) separated by ‘.’.
var restoreIpAddresses = function(s) {
let res = [];
if(s.length < 4 || s.length > 12) return res;
function dfs(s, sub, index) {
if(s.length === 0 && index === 4) res.push(sub.slice(1)); // Remove the beginning.
if(s.length === 0 || index === 4) return;
/ / a number
dfs(s.slice(1), `${sub}.${s.slice(0.1)}`, index + 1);
if(s[0]! = ='0' && s.length > 1) {
dfs(s.slice(2), `${sub}.${s.slice(0.2)}`, index + 1); / / two Numbers
if(s.length > 2 && parseInt(s.slice(0.3)) < =255) {
dfs(s.slice(3), `${sub}.${s.slice(0.3)}`, index + 1); / / number three
}
}
}
dfs(s, ' '.0);
return res;
};
Copy the code
Sorting algorithm
Bubble sort
Compare the size of the two records’ key values, and swap the records if the size of the two records’ key values is reversed
function bubbleSort(arr){
for(let i = 1; i < arr.length; i++){for(letj = i; j >0; j--){if(arr[j] < arr[j- 1]){
[arr[j],arr[j- 1]] = [arr[j- 1],arr[j]]; }}}return arr;
}
Copy the code
Fast row
In n records from a record for the key value standard, usually the first record key value as a benchmark, sort through a trip to rows of records can be divided into less than or equal to the key value of two separate parts, it is part of the record key values are smaller than another part of the record of the key value, then, for the two parts record to continue separately quick sort, in order to achieve the orderly sequence
function quickSort(arr){
if(arr.length <= 1) return arr;
let right = [],left = [],keys = arr.shift();
for(let value of arr){
if(value > keys){
right.push(value)
}else{ left.push(value); }}return quickSort(left).concat(keys,quickSort(right));
}
Copy the code
Insertion sort
When the I th record (I greater than or equal to 1) is inserted, R1, R2… Is the sorted sequence. Take out the ith element, find a suitable position in the sequence and insert it into the position.
function insertSort(arr){
for(let i = 1; i < arr.length; i++){let j = i- 1;
if(arr[i]<arr[j]){
let temp = arr[i];
while(j >= 0 && temp < arr[j]){
arr[j+1] = arr[j];
j--;
}
arr[j+1] = temp; }}return arr;
}
Copy the code
Hill sorting
The algorithm first divides the group of numbers to be sorted into several groups according to some increment D (n/2,n is the number of numbers to be sorted), and the difference of the subscripts recorded in each group is D. Direct insertion sort is done for all the elements in each group, then it is grouped by a small increment (D /2), and then direct insertion sort is done for each group. When the increment is reduced to 1, the sort is completed after the direct insertion sort.
function hillSort(arr){
let len = arr.length;
for(let gap = parseInt(len >> 1); gap >=1; gap =parseInt(gap >> 1)) {for(leti = gap; i < len; i++){if(arr[i] < arr[i-gap]){
let temp = arr[i];
let j = i - gap;
while(j >= 0&& arr[j] > temp){ arr[j+gap] = arr[j]; j -= gap; } arr[j+gap] = temp; }}}return arr;
}
Copy the code
Selection sort
In the i-th selection operation, the record with the smallest key value is selected from n-i+1 records by comparing the key-values of n-i, and the record is exchanged with the i-th records (1 is less than or equal to 1 is less than or equal to N-1)
function selectSort(arr){
for(let i = 0; i < arr.length; i++){let min = Math.min(... arr.slice(i));let index = arr.indexOf(min);
[arr[i],arr[index]] = [arr[index],arr[i]];
}
return arr;
}
Copy the code
Heap sort
function adjustMaxHeap(heap,head,heapSize){
let temp = heap[head];
let child = head * 2 + 1;
while(child < heapSize){
if(child+1 < heapSize && heap[child] < heap[child+1]) child++;
if(heap[head] < heap[child]){
heap[head] = heap[child];
head = child;
child = head * 2 + 1;
}else break; heap[head] = temp; }}function buildHeap(heap){
for(let i = (heap.length- 1) > >1; i >=0;i--){
adjustMaxHeap(heap,i,heap.length);
}
}
function heapSort(arr){
buildHeap(arr);
for(let i = arr.length- 1; i >0; i--){ [arr[i],arr[0]] = [arr[0],arr[i]];
adjustMaxHeap(arr,0,i);
}
return arr;
}
Copy the code
Merge sort
Treat an unordered file with n records as a file consisting of n ordered subfiles of length 1, and then merge them pairwise
function MergeSort(arr,left,right){
if(left >= right) return;
let mid = Math.floor((right - left) >> 1) + left;
MergeSort(arr,left,mid);
MergeSort(arr,mid+1,right);
Merge(arr,left,mid,right);
return arr;
}
function Merge(arr,left,mid,right){
let temp = [],i = 0;
let p1 = left,p2 = mid + 1;
while(p1 <= mid && p2 <= right){
arr[p1] <= arr[p2] ? temp[i++] = arr[p1++] : temp[i++] = arr[p2++];
}
while(p1 <= mid){
temp[i++] = arr[p1++];
}
while(p2 <= right){
temp[i++] = arr[p2++];
}
for(let i = 0; i < temp.length; i++){ arr[i+left] = temp[i]; }}Copy the code
Bucket sort
Group the data into buckets and sort the contents of each bucket
function radixSort(arr,arrDomain,gropSize){
let data = [];
for(let i = 0; i < arr.length; i++) data.push([]);console.log(data)
for(let i = 0; i < arr.length; i++){ data[Math.floor(parseInt(arr[i] / gropSize)) + 1].push(arr[i]);
}
for(let i = 0; i < data.length; i++){ quickSort(data[i]); }return data.flat(Infinity);
}
Copy the code
The stability, time complexity and space complexity of each sorting algorithm
The system comes with sorting implementation
The internal implementation of sorting is different for each language.
For JS, arrays larger than 10 will be quicksorted, otherwise insertion sort will be used. Insertion sort is chosen because, although the time complexity is very poor, it is about the same as O(N * logN) for a small amount of data, and insertion sort takes a very small constant time, so it is faster than other sorts.
The stability of
Stability means that relative order cannot be changed for the same value. The colloquial way of saying that you have two identical numbers, A and B, before sorting A is in front of B, and after sorting B is in front of A, and when that happens, we call it sorting instability.
What does stability mean? For the front end, for example, we are familiar with the virtual DOM comparison in the framework. We render a list, and when the data changes and the comparison changes, unstable ordering or operation will make the things that do not need to change change, resulting in re-rendering and performance loss.
Rank interview Questions
- Quicksort works best when it is completely unordered, with time complexity of O(nlogn), and worst when it is ordered, with time complexity of O(n^2).
- The most common external sort algorithm is merge sort.
- Insertion sort works best when the array is basically ordered, because you only have to compare sizes, you don’t have to move, and the time complexity tends to O(n).
- If you only want to get a partially sorted sequence before the fifth smallest element in a sequence of 1000 elements, heapsort is the fastest.
- Quicksort a linear table of length n, with n(n-1)/2 comparisons in the worst case.
exercises
Sorting list
The list is sorted in order (n log n) time complexity and constant space complexity.
var sortList = function(head) {
let mergeList = (left,right) = > {
let res = new ListNode(0);
let pre = res;
while(left && right){
if(left.val <= right.val){
pre.next = left;
left = left.next;
}else{
pre.next = right;
right = right.next;
}
pre = pre.next;
}
pre.next = left ? left : right;
return res.next;
}
let mergeSort = (node) = > {
if(! node || ! node.next)return node;
let mid = node;
let fast = node.next;
while(fast && fast.next){
mid = mid.next;
fast = fast.next.next;
}
let rightList = mid.next;
mid.next = null;
let left = node;
let right = rightList;
return mergeList(mergeSort(left),mergeSort(right));
}
return mergeSort(head);
};
Copy the code
The reverse of
Two digits in an array that form a reverse pair if the first digit is greater than the second. Enter an array and find the total number of reverse pairs in that array, P. And output the result of P modulo to 1000000007. The output P % 1000000007
let count = 0;
function InversePairs(data)
{
if (data == null || data.length == 0) {
return 0;
}
MergeSort(data,0,data.length- 1);
return count % 1000000007;
}
function MergeSort(arr,left,right){
if(left >= right) return;
let mid = Math.floor((right - left)>>1) + left;
MergeSort(arr,left,mid);
MergeSort(arr,mid+1,right);
Merge(arr,left,mid,right);
}
function Merge(arr,left,mid,right) {
let temp = [],i = 0;
let p1 = left,p2 = mid + 1;
while(p1 <= mid && p2 <= right){
if(arr[p1] <= arr[p2]){
temp[i++] = arr[p1++];
}else{
count += mid - p1 + 1; temp[i++] = arr[p2++]; }}while(p1 <= mid){
temp[i++] = arr[p1++];
}
while(p2 <= right){
temp[i++] = arr[p2++];
}
for(let i = 0; i < temp.length; i++){ arr[i+left] = temp[i]; }}Copy the code
Check and set
It is a special data structure and has good performance in solving the problem of connected domain.
Three components
-
Maintain an array, let parents = [], that holds the current node’s parent, the root node’s parent being itself.
-
Example Query the root node of a node.
function find(root){ let temp,son = root; while(root ! == parents[root]){ root = parents[root]; }while(son ! == root){// Path compression is a flattening process temp = parents[son]; parents[son] = root; son = temp; } return root; } / / the recursive version function find(root){ if(root ! == parents[root]) parents[root] = find(parents[root]);return parents[root]; } Copy the code
-
Merge two connected domains
function join(x,y){ x = find(x); y = find(y); if(x !== y){ parents[x] = y; } } Copy the code
exercises
The number of islands
- Write the three components, starting with parents by matching their key to their value
- Determine if there is land around the current node, if so, connect them, if not, invert the parent node of the current node
- Find the number of keys and values in the Parents array that are still equal (that is, the number of connected fields)
var numIslands = function(grid) {
let row = grid.length;
if(row === 0) return 0;
let col = grid[0].length;
let parents = [];
for(let i = 0; i < row; i++){for(let j = 0; j < col; j++){ parents[i*col+j] = i * col + j; }}function find(root){
if(root ! == parents[root]) parents[root] = find(parents[root]);return parents[root];
}
function union(x,y){
x = find(x);
y = find(y);
if(x !== y){
parents[x] = y;
}
}
for(let i = 0; i < row; i++){for(let j = 0; j < col; j++){if(grid[i][j] === '1'){
i < row- 1 && grid[i+1][j] === '1' && union((i+1)*col+j,i*col+j);
j < col- 1 && grid[i][j+1= = ='1' && union(i*col+j+1,i*col+j);
}else{ parents[i*col+j] = -parents[i*col+j]; }}}return parents.filter((value,key) = > (key === value && Object.is(key,value))).length;
};
Copy the code
DFS is the solution to
var numIslands = function(grid) {
const row = grid.length;
if(! row)return 0;
const col = grid[0].length;
let res = 0;
for(let i = 0; i < row; i++) {
for(let j = 0; j < col; j++) {
if(grid[i][j] === '1') { res++; dfs(grid, i, j); }}}function dfs(grid, i, j) {
if(i < 0 || i >= row || j < 0 || j >= col) return;
if(grid[i][j] === '1') {
grid[i][j] = '0';
dfs(grid, i - 1, j);
dfs(grid, i + 1, j);
dfs(grid, i, j - 1);
dfs(grid, i, j + 1); }}return res;
};
Copy the code
The area that is surrounded
- Write three major components
- will
O
Nodes are divided into internal nodes and boundary nodes, and a virtual boundary root node is introduced - determine
O
Whether the node is an internal node. If yes, replace withX
var solve = function(board) {
let row = board.length;
if(row === 0) return board;
let col = board[0].length;
let parents = [];
for(let i = 0; i < row; i++){for(let j = 0; j < col; j++){ parents[i*col+j] = i * col + j; }}function find(root){
if(root ! == parents[root]) parents[root] = find(parents[root]);return parents[root];
}
function union(x,y){
x = find(x);
y = find(y);
if(x !== y){
parents[x] = y;
}
}
function isConnected(x,y){
return find(x) === find(y);
}
let virtualArea = row * col + 1;
for(let i = 0; i < row; i++){for(let j = 0; j < col; j++){if(board[i][j] === 'O') {if(i === 0 || i === row- 1 || j === 0 || j === col- 1){
union(i*col+j,virtualArea);
}else{
i > 0 && board[i- 1][j] === 'O' && union(i*col+j,(i- 1)*col+j);
i < row- 1 && board[i+1][j] === 'O' && union(i*col+j,(i+1)*col+j);
j > 0 && board[i][j- 1= = ='O' && union(i*col+j,i*col+j- 1);
j < col- 1 && board[i][j+1= = ='O' && union(i*col+j,i*col+j+1); }}}}for(let i = 0; i < row; i++){for(let j = 0; j < col; j++){if(board[i][j] === 'O' && !isConnected(i*col+j,virtualArea)){
board[i][j] = 'X'; }}}return board;
};
Copy the code
A topological sort
Topological ordering of a Directed Acyclic Graph (DAG)G is to arrange all vertices in G into a linear sequence, such that any pair of vertices u and V in the Graph appear before V in the linear sequence if edge
∈E(G). In general, such linear sequences are called Topological Order sequences, or Topological sequences for short. In simple terms, a partial order in a set leads to a total order in that set. This operation is called topological sorting. I have to say that the encyclopedia’s interpretation is very professional, but it just doesn’t know what to say (WTCL).
,v>
For example
- For directed acyclic graphs, we first find a node (any one) with an entry degree of zero.
- Delete the node, store the value of the node in the result array, and then subtract 1 from the input degree of all the nodes adjacent to the node
- Find another node with an input degree of 0 and repeat operation 2
- All the remaining values of the zero input nodes are stored in the result array.
How to build figure
Topological sorting involves the deletion of nodes, so it is a good choice to use the data structure of adjacencies to represent graphs
Adjacency list
// Here is a simple adjacencies list (for test programming), which is in the exercise section
class Node{
constructor(value){
this.value = value;
this.next = null;
this.in = 0; // Record the input}}class Graph{
constructor(nodeNum,edges){
this.list = new Array(nodeNum);
for(let i = 0; i <this.list.length; i++){// Initialize the adjacency list
this.list[i] = new Node(i);
}
let v1,v2,newNode = null;
for(let edge of edges){ // Construct the adjacencies list and the intakes of each node
[v2,v1] = edge;
newNode = new Node(v2);
newNode.next = this.list[v1].next;
this.list[v1].next = newNode;
this.list[v2].in++; }}}Copy the code
I like to see the exercises
Schedule II
Now you have a total of N courses to take, zero through n minus one.
Some prerequisite courses are required before you can take certain courses. For example, to learn lesson 0, you need to complete lesson 1 first, and we represent them with a match: [0,1]
Given the total number of courses and their prerequisites, returns the order in which you studied in order to complete all the courses.
There could be multiple correct orders, and you just have to return one. If it is not possible to complete all the courses, return an empty array.
- Establish the adjacency list
- Create a null node in the secondary stack, a result array res to store the results, and a counter count to record the number of deleted nodes
- Each time we take a node in the helper stack, we subtract the input degree of all its adjacent nodes to determine whether the input degree is zero (thus adding to the helper stack), and put the node value into res, count++
- Determine whether the counter is the same as the number of nodes in the graph. If not, prove that there is a loop. Just return the value as the problem asks
class Node{
constructor(value){
this.value = value;
this.next = null;
this.in = 0; }}class Graph{
constructor(nodeNum,edges){
this.list = new Array(nodeNum);
for(let i = 0; i <this.list.length; i++){this.list[i] = new Node(i);
}
let v1,v2,newNode = null;
for(let edge of edges){
[v2,v1] = edge;
newNode = new Node(v2);
newNode.next = this.list[v1].next;
this.list[v1].next = newNode;
this.list[v2].in++; }}}var findOrder = function(numCourses, prerequisites) {
let list = new Graph(numCourses,prerequisites).list;
let stack = [],res = [];
for(let node of list){
node.in === 0 && stack.push(node);
}
let count = 0;
while(stack.length){
let node = stack.pop();
count++;
res.push(node.value);
while(node.next){
(--list[node.next.value].in) === 0&& stack.push(list[node.next.value]); node = node.next; }}if(count ! == list.length)return [];
else return res;
};
Copy the code
The curriculum
You must take numCourse 0 through numCourse-1 this semester.
Some prerequisite courses are required before you can take certain courses. For example, to learn lesson 0, you need to complete lesson 1 first, and we represent them with a match: [0,1]
Given the total number of courses and their prerequisites, do you think it is possible to complete all of them?
// Let's look at the code
class Node{
constructor(value){
this.value = value;
this.next = null;
this.in = 0; }}class Graph{
constructor(nodeNum,edges){
this.list = new Array(nodeNum);
for(let i = 0; i <this.list.length; i++){this.list[i] = new Node(i);
}
let v1,v2,newNode = null;
for(let edge of edges){
[v2,v1] = edge;
newNode = new Node(v2);
newNode.next = this.list[v1].next;
this.list[v1].next = newNode;
this.list[v2].in++; }}}var canFinish = function(numCourses, prerequisites) {
let list = new Graph(numCourses,prerequisites).list;
let stack = [];
for(let node of list){
node.in === 0 && stack.push(node);
}
let count = 0;
while(stack.length){
let node = stack.pop();
count++;
while(node.next){
(--list[node.next.value].in) === 0&& stack.push(list[node.next.value]); node = node.next; }}return count === list.length
};
Copy the code
An operation
The number of ones in binary
Implement a function that inputs an integer and outputs the number of 1s in the binary representation of that number. For example, the binary representation of 9 is 1001, with 2 bits being 1. Therefore, if the input is 9, the function outputs 2
//n & (n-1) the number of 1 at a time
var hammingWeight = function(n) {
let count = 0;
while(n){
count++;
n = n & (n- 1);
}
return count;
};
Copy the code
Find a number that appears more than half the length of the array
// for example, enter an array of length 9 {1,2,3,2,2,2,5,4,2}. Since the number 2 appears in the array five times, more than half the length of the array, output 2. Output 0 if it does not exist.
1.Initialize count to0, and count the = = =0When res = the current number, count++2.The current number is the same as res count++, otherwise count--3.The above two steps can select the number that appears the most, and then judge whether it is more than halffunction MoreThanHalfNum_Solution(numbers)
{
let result,count=0;
for(let i = 0; i < numbers.length; i++){if(count === 0){
result = numbers[i];
count++;
}else{
if(result === numbers[i]){
count++;
}else{ count--; }}}let times = numbers.filter(x= > x === result).length;
return times > Math.floor(numbers.length >> 1)? result :0;
}
Copy the code
Numbers that only appear once
Given an array of non-empty integers, each element appears twice except for one that appears only once. Find the element that appears only once
var singleNumber = function(nums) {
let num = nums[0];
for(let i = 1; i < nums.length; i++){ num ^= nums[i]; }return num;
};
Copy the code
Bit count
Given a non-negative integer num. For each number I in the range 0 ≤ I ≤ num, count the number of 1s in its binary number and return them as an array
1.An odd number1The number of PI is equal to the previous even number plus PI1
2.An even number1Is equal to the current even number >>1The value of thevar countBits = function(num) {
let res = [0];
for(let i = 1; i <= num; i++){if(i & 1){
res[i] = res[i- 1] + 1;
}else{
res[i] = res[i >> 1]; }}return res;
};
Copy the code
Hamming distance
The Hamming distance between two integers is the number of different positions in which the two digits correspond to the binary bits.
Given two integers x and y, calculate the Hamming distance between them
1.Or you can figure out the different parts2.statisticalvar hammingDistance = function(x, y) {
let ans = x ^ y,count = 0;
while(ans){
if(ans & 1) count++;
ans = ans >> 1;
}
return count;
};
Copy the code
Write a function, find the sum of two integers, requirements in the function body should not use +, -, *, / four operation symbols
1.^ Non-carry addition2.& Determine the carry point3. << 1carryfunction Add(num1, num2)
{
return num2 ? Add(num1 ^ num2,(num1 & num2) << 1) : num1;
}
Copy the code
Double pointer
As the name suggests, use two Pointers to find, improve the efficiency of the search
The sum of n number
The sum of two Numbers
var twoSum = function(nums, target) {
if(! nums.length)return [];
let num = nums.slice(0);
nums.sort((x,y) = > x-y);
let l = 0,r = nums.length- 1;
while(l < r){
if(nums[l] + nums[r] === target) break;
else if(nums[l] + nums[r] < target){
l++;
}else{
r--;
}
}
l = num.indexOf(nums[l]);
r = num.indexOf(nums[r]) === l ? num.indexOf(nums[r],l+1) : num.indexOf(nums[r])
return [l,r];
};
Copy the code
The sum of three number
var threeSum = function(nums) {
if(nums.length < 3) return [];
nums.sort((x,y) = > x-y);
let res = [];
for(let i = 0; i < nums.length; i++){// If the first term is greater than 1, there is no need to arrange
if(nums[i] > 0) return res;
/ / to heavy
if(i && nums[i] === nums[i- 1]) continue;
let left = i+1,right = nums.length- 1;
while(left < right){
if(nums[left] + nums[right] + nums[i] === 0){
res.push([nums[i],nums[left],nums[right]]);
/ / to heavy
while(left < right && nums[left] === nums[left+1]){
left++;
}
while(left < right && nums[right] === nums[right- 1]){
right--;
}
left++;
right--;
}else if(nums[left] + nums[right] + nums[i] > 0){
right--;
}else{ left++; }}}return res;
};
Copy the code
The sum of the three closest numbers
// The idea is the same as before, but two variables are required, one to update the answer and one to update the minimum difference
var threeSumClosest = function(nums, target) {
if(! nums.length)return 0;
let res = Infinity,mins = Infinity;
nums.sort((x,y) = > x-y);
for(let i = 0; i < nums.length; i++){let left = i + 1,right = nums.length- 1;
while(left < right){
mins = Math.min(Math.abs(nums[i]+nums[left]+nums[right]-target),mins);
mins === Math.abs(nums[i]+nums[left]+nums[right]-target)
&& (res = nums[i]+nums[left]+nums[right]);
if(nums[i]+nums[left]+nums[right] < target){
left++;
}else if(nums[i]+nums[left]+nums[right] > target){
right--;
}else{
break; }}}return res;
};
Copy the code
Rainwater, container problems
The container that holds the most water
// Update the maximum value at the time of the double pointer
var maxArea = function(height) {
if(! height.length)return 0;
let left = 0,right = height.length- 1,res = 0;
while(left < right){
if(height[left] <= height[right]){
let cur = height[left] * (right - left);
res = Math.max(res,cur);
left++;
}else{
let cur = height[right] * (right - left);
res = Math.max(res,cur); right--; }}return res;
};
Copy the code
After the rain
// How to obtain the rainwater stored in each cell
// Take the left side as an example: current column capacity = the height of the most recent column (see left to current column only) - current column height
// The right-hand side is the same
function trap(arr){
if(! arr.length)return 0;
let left = 0,right = arr.length- 1,leftHeight = 0,rightHeight = 0,res = 0;
while(left < right){
if(arr[left] < arr[right]){
leftHeight = Math.max(arr[left],leftHeight);
res += leftHeight - arr[left];
left++;
}else{
rightHeight = Math.max(arr[right],rightHeight); res += rightHeight - arr[right]; right--; }}return res;
}
Copy the code
Minimum length subarray
Given an array of n positive integers and a positive integer s, find the contiguous subarray of the array with the smallest length such that its sum is ≥ s and return its length. Return 0 if no contiguous subarray exists.
// The sliding window solution
// Add the number corresponding to the right pointer to the temporary num each time
If len is a feasible solution, then len is compared with len, and the left pointer is moved
// Move the right pointer to the next position
var minSubArrayLen = function(s, nums) {
let left = 0, right = 0, len = Infinity, num = 0;
while(right < nums.length) {
num += nums[right];
while(num >= s) {
len = Math.min(len, right - left + 1);
num -= nums[left];
left++;
}
right++;
}
return len === Infinity ? 0 : len;
};
Copy the code
Linked list class
Deletes the NTH node from the list
var removeNthFromEnd = function(head, n) {
if(! head)return null;
let fast = head,slow = head,pre = head,p1 = head,len = 0;
while(p1){
len++;
p1 = p1.next;
}
// Note that the header node is deleted
if(len === n) return head.next;
while(n--){
fast = fast.next;
}
while(fast){
fast = fast.next;
pre = slow;
slow = slow.next;
}
pre.next = slow.next;
return head;
};
Copy the code
Please determine whether a linked list is a palindrome list
1.Inverts the first half of the linked list2.Determine whether the two parts of the list are equalvar isPalindrome = function(head) {
if(! head)return true;
let pre = null,temp,fast = head,slow = head;
while(fast && fast.next){
fast = fast.next.next;
// Reverse the list
temp = slow;
slow = slow.next;
temp.next = pre;
pre = temp;
}
if(fast) slow = slow.next;
while(pre && slow){
if(pre.val ! == slow.val)return false;
pre = pre.next;
slow = slow.next;
}
return true;
};
Copy the code
Given a linked list, determine whether there are rings in the list
var hasCycle = function(head) {
if(! head || ! head.next || ! head.next.next)return false;
let fast = head.next.next,slow = head.next;
while(fast ! == slow){if(fast === null || fast.next === null) return false;
fast = fast.next.next;
slow = slow.next;
}
return true;
};
Copy the code
Input a linked list, output the KTH node in the list.
function FindKthToTail(head, k)
{
// write code here
if(head === null || k === 0) return null;
let fast = head,slow = head;
while(k--){
if(fast === null) return null;
fast = fast.next;
}
while(fast){
fast = fast.next;
slow = slow.next;
}
return slow;
}
Copy the code
Input two monotonically increasing lists, output two lists after the synthesis of the list, of course, we need to synthesis of the list to meet the monotonic rule.
// Note the distinction between copied lists
function Merge(pHead1, pHead2)
{
if(pHead1 === null) {return pHead2;
}else if(pHead2 === null) {return pHead1;
}
if(pHead1.val < pHead2.val){
pHead1.next = Merge(pHead1.next,pHead2);
return pHead1;
}else{
pHead2.next = Merge(pHead2.next,pHead1);
returnpHead2; }}Copy the code
Enter two linked lists and find their first common node
function FindFirstCommonNode(pHead1, pHead2)
{
// write code here
let p1 = pHead1,p2 = pHead2;
while(p1 ! == p2){ p1 = p1 ===null ? pHead2 : p1.next;
p2 = p2 === null ? pHead1 : p2.next;
}
return p1;
}
Copy the code
Find the ring list into the ring location
var detectCycle = function(head) {
if(! head || ! head.next)return null;
let fast = head.next.next,slow = head.next,p1 = head;
while(fast ! = =null&& fast ! == slow){if(fast.next) fast = fast.next.next;
else fast = null;
slow = slow.next;
}
if(fast === null) return null;
else{
while(p1 ! == slow){ p1 = p1.next; slow = slow.next; }returnslow; }};Copy the code
String class
Verify palindrome strings
var isPalindrome = function(s) {
let reg = /[a-z]|[0-9]/;
s = s.split(' ').map(x= > x.toLowerCase()).filter((x) = > reg.test(x)).join(' ');
let head = 0;
let tail = s.length- 1;
while(head <= tail){
if(s[head] ! == s[tail])return false;
head++;
tail--;
}
return true;
};
Copy the code
matrix
Print the matrix clockwise
Enter a matrix and print out each number in clockwise order from the outside in
/ /, for example, if the input is as follows: 4 X 4 matrix 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10, in turn, print out the number 1.Spin magic method, print the first column each time, and then rotate the matrix counterclockwisefunction rotate(arr){
if(! arr.length)return [];
let newArr = [];
for(let i = 0; i < arr[0].length; i++){let temp = [];
for(let j = 0; j < arr.length; j++){ temp.push(arr[j][arr[0].length- 1-i]);
}
newArr.push(temp);
}
return newArr;
}
function printMatrix(matrix)
{
if(! matrix.length)return [];
let ans = [];
while(matrix.length){
for(let i = 0; i < matrix[0].length; i++){ ans.push(matrix[0][i])
}
matrix.splice(0.1);
matrix = rotate(matrix);
}
return ans;
}
Copy the code
Rotate the image
Given an n by n two-dimensional matrix representing an image.
Rotate the image 90 degrees clockwise
var rotate = function(matrix) {
if(! matrix.length)return [];
let left = 0,right = matrix.length- 1;
while(right-left > 0){
[matrix[left],matrix[right]] = [matrix[right],matrix[left]];
left++;
right--;
}
for(let i = 0; i < matrix.length; i++){for(let j = i+1; j < matrix[i].length; j++){ [matrix[i][j],matrix[j][i]] = [matrix[j][i],matrix[i][j]]; }}return matrix;
};
Copy the code
Spiral matrix II
Given a positive integer n, a square matrix containing all the elements from 1 to n2 is generated with the elements spiraling clockwise
// This process is basically simulated, paying attention to the boundary conditions of the turn
var generateMatrix = function(n) {
let rows = n- 1,cols = n- 1,col = 0,row = 0,iter = 1,x_dire = 1,y_dire = 1,cur_dire = 1,res = [];
for(let i = 0; i < n; i++) res.push([]);while(iter <= n ** 2) {
if (cur_dire === 1 && res[row][col] === undefined) {
res[row][col] = iter;
iter++;
if (x_dire === 1) {
if (col < cols) {
col++;
} else {
cur_dire = - 1;
x_dire = -x_dire;
if (y_dire === 1) row++;
elserow--; }}else {
if (col > 0) {
col--;
} else {
cur_dire = - 1;
x_dire = -x_dire;
if (y_dire === 1) row++;
elserow--; }}}else if (cur_dire === 1 && res[row][col]) {
if (y_dire === 1) row++;
else row--;
x_dire = -x_dire;
cur_dire = - 1;
if (x_dire === 1) col++;
else col--;
}else if (cur_dire === - 1 && res[row][col] === undefined) {
res[row][col] = iter;
iter++;
if (y_dire === 1) {
if (row < rows) {
row++;
} else {
cur_dire = 1;
y_dire = -y_dire;
if (x_dire === 1) col++;
elsecol--; }}else {
if (row >= 0) {
row--;
} else {
cur_dire = 1;
y_dire = -y_dire;
if (x_dire === 1) col++;
elsecol--; }}}else if(cur_dire === - 1 && res[row][col]) {
if (x_dire === 1) col++;
else col--;
y_dire = -y_dire;
cur_dire = 1;
if (y_dire === 1) row++;
elserow--; }}return res;
};
Copy the code
Matrix zero
Given an m x N matrix, if one of the entries is 0, then all the entries in its row and column are set to 0. Please use the ** in place ** algorithm
// Use the js feature, -0 and 0 are not equal
// Set the non-zero element in the row of 0 to -0
var setZeroes = function(matrix) {
for(let i = 0; i < matrix.length; i++){for(let j = 0; j < matrix[i].length; j++){if(Object.is(matrix[i][j],0)) {for(let k = 0; k < matrix.length; k++){if(k ! == i &&Object.is(matrix[k][j],0)) continue;
else matrix[k][j] = 0
}
for(let k = 0; k < matrix[i].length; k++){if(k ! == j &&Object.is(matrix[i][k],0)) continue;
else matrix[i][k] = 0}}}}return matrix;
};
Copy the code
Yang hui triangle
/ / into the pit
function print(n) {
let arr = [],n1 = n;
while(n1--){
arr.push([]);
}
for(let i = 0; i < n; i++){for(let j = 0; j <= i; j++){if(j === 0 || j === i) arr[i][j] = 1;
else{
arr[i][j] = arr[i- 1][j- 1]+arr[i- 1][j];
}
}
}
arr.forEach(x= > console.log(x.toString().replace(/,/g.' ')));
}
Copy the code
Binary tree
Traverse series
Sequential traversal of binary trees (recursive and non-recursive)
/ / recursion
function pre(root){
if(! root)return root;
console.log(root.val);
pre(root.left);
pre(root.right);
}
function mid(root){
if(! root)return root;
mid(root.left);
console.log(root.val);
mid(root.right);
}
function next(root){
if(! root)return root;
next(root.right);
next(root.left);
console.log(root.val);
}
/ / the recursion
/ / before order
// Simulate with stack
// Add the top element to the result each time, and then push the left and right non-empty subtrees of the top element (notice that the right subtree is pushed first, then pops up).
// Break the loop until the stack is empty
function pre(root){
if(root === null) return root;
let res = [],stack = [];
stack.push(root);
while (stack.length){
let node = stack.pop();
res.push(node.val);
node.right && stack.push(node.right);
node.left && stack.push(node.left);
}
return res;
}
/ / in the sequence
// Iterate through the left subtree of the top element of the stack, then add the top of the stack to the result, then access the right subtree of the current child node, and so on
function mid(root){
if(root === null) return root;
let res = [],stack = [];
stack.push(root);
while (stack.length){
while(root ! = =null){
stack.push(root);
root = root.left;
}
let node = stack.pop()
res.push(node.val);
root = node.right;
}
// The root node was added twice
return res.slice(0,res.length- 1);
}
/ / after order
// This is similar to the previous order, but the root is generated in the right and left order, and the res is reversed
function next(root){
if(root === null) return root;
let res = [],stack = [];
stack.push(root);
while (stack.length){
let node = stack.pop();
res.push(node.val);
node.left && stack.push(node.left);
node.right && stack.push(node.right);
}
return res.reverse();
}
Copy the code
Level traversal
var levelOrder = function(root) {
if(! root)return [];
let nodes = [],queue = [root],path=[];
let cur = 1,next = 0;
while(queue.length){
let node = queue.shift();
path.push(node.val);
node.left && queue.push(node.left) && next++;
node.right && queue.push(node.right) && next++;
cur--;
if(! cur){ nodes.push(path); path = []; cur = next; next =0; }}return nodes;
};
Copy the code
Traverse the variant
Zigzag hierarchical traversal of binary trees
Given a binary tree, return a zigzag hierarchical traversal of its node values. (that is, first from left to right, then from right to left to the next layer, and so on, alternating between layers).
var zigzagLevelOrder = function(pRoot) {
if(! pRoot) {return[]}var queue = [], res = [], temp = [],
node, level = 0, toBePrinted = 1, isEven = true;
queue.push(pRoot);
while(queue.length) {
node = queue.shift();
// Determine whether the current behavior is odd or even
if(isEven) {
temp.push(node.val);
} else {
temp.unshift(node.val);
}
// Count the number of elements per row
if(node.left) {
queue.push(node.left);
level++;
}
if(node.right) {
queue.push(node.right);
level++;
}
toBePrinted--;
// Check whether the current line is finished
if(toBePrinted === 0) {
res.push(temp);
temp = [];
toBePrinted = level;
level = 0;
isEven = !isEven;
}
}
return res;
};
Copy the code
Print binary tree by pressing layer from top to bottom, node of the same layer output from left to right. Each layer outputs one line.
// Add two variables to BFS, one to store the number of nodes in the current level and one to store the number of nodes in the next level (++ for each queue push)
function Print(pRoot) {
let nodes = [],queue = [pRoot],path=[];
let cur = 1,next = 0;
while(queue.length){
let node = queue.shift();
path.push(node.val);
node.left && queue.push(node.left) && next++;
node.right && queue.push(node.right) && next++;
cur--;
if(! cur){ nodes.push(path); path = []; cur = next; next =0; }}return nodes;
}
Copy the code
Given the binary tree, let’s find some value
Find the depth of the binary tree
function TreeDepth(pRoot)
{
if(pRoot === null) return 0;
let left = TreeDepth(pRoot.left);
let right = TreeDepth(pRoot.right);
return Math.max(left,right) + 1;
}
Copy the code
The KTH smallest element in the binary search tree
var kthSmallest = function(root, k) {
let res;
function midOrder(root){
if(! root)return root;
midOrder(root.left);
if(k === 0) return res;
else{
res = root.val;
k--;
}
midOrder(root.right);
}
midOrder(root);
return res;
};
Copy the code
The nearest common ancestor of a binary tree
(1If you find either of the two nodes, return (2Return root if both nodes are found, otherwisenull
var lowestCommonAncestor = function(root, p, q) {
if(! root)return null;
if(root === p || root === q) return root;
let left = lowestCommonAncestor(root.left,p,q);
let right = lowestCommonAncestor(root.right,p,q);
if(! left)return right;
if(! right)return left;
if(left && right) return root;
return null;
};
Copy the code
Given a binary tree, you need to calculate its diameter.
The diameter length of a binary tree is the maximum of the path length of any two nodes. This path may or may not go through the root.
Error prone point is the diameter may not pass through the root node with Max to save the maximum, when each node as the root node, compared with Max updatevar diameterOfBinaryTree = function(root) {
let max = 0;
function dfs(root){
if(! root)return 0;
let l = dfs(root.left);
let r = dfs(root.right);
max = Math.max(max,l+r);
return Math.max(l,r)+1;
}
dfs(root);
return max;
};
Copy the code
Sum the numbers from the root to the leaves
Given a binary tree, each node contains a number from 0 to 9, and each path from the root to the leaf node represents a number.
For example, the path 1->2->3 from the root to the leaf node represents the number 123.
Calculates the sum of all the numbers generated from the root to the leaf node.
Note: A leaf node is a node with no child nodes.
// Simple DFS
var sumNumbers = function(root) {
let res = 0;
function dfs(root,temp) {
if(! root)return;
temp += root.val;
if((! root.left) && (! root.right)) res +=Number(temp);
dfs(root.left,temp);
dfs(root.right,temp);
}
dfs(root,' ');
return res;
};
Copy the code
Some special binary trees (judgment and construction)
Determine whether the binary tree is a symmetric binary tree
function mirrors(root)
{
if(root === null) return root;
[root.left,root.right] = [root.right,root.left];
mirrors(root.left);
mirrors(root.right);
}
var isSymmetric = function(root) {
let mirror = JSON.parse(JSON.stringify(root));
mirrors(mirror);
if(JSON.stringify(mirror) === JSON.stringify(root)){
return true;
}else{
return false; }};Copy the code
Verify the binary search tree
Given a binary tree, judge whether it is a valid binary search tree.
let pre = -Infinity;
var isValidBST = function(root) {
if(! root)return true;
let left = isValidBST(root.left);
if(root.val <= pre || ! left)return false;
pre = root.val;
return isValidBST(root.right);
};
Copy the code
Construct binary trees from preordered and ordinal traversal sequences
var buildTree = function(preorder, inorder) {
if(! preorder.length || ! inorder.length)return null;
let root = new TreeNode(preorder[0]);
let key = 0;
for(let i = 0; i < inorder.length; i++){if(inorder[i] === preorder[0]){
key = i;
break;
}
}
root.left = buildTree(preorder.slice(1,key+1),inorder.slice(0,key));
root.right = buildTree(preorder.slice(key+1),inorder.slice(key+1));
return root;
};
Copy the code
Flip the binary tree
var invertTree = function(root) {
if(root === null) return root;
[root.left,root.right] = [root.right,root.left];
invertTree(root.left);
invertTree(root.right);
return root;
};
Copy the code
Convert a binary search tree to an accumulation tree
var convertBST = function(root) {
let cur = 0;
re = function(root){
if(! root)return root;
re(root.right);
root.val += cur;
cur = root.val;
re(root.left);
return root;
}
return re(root);
};
Copy the code
Merge binary trees
var mergeTrees = function(t1, t2) {
if(t1 && t2){
t1.val += t2.val;
t1.left = mergeTrees(t1.left,t2.left);
t1.right = mergeTrees(t1.right,t2.right);
}
return t1 || t2;
};
Copy the code
Input two binary trees A, B, and determine whether B is A substructure of A
(ps: we agree that an empty tree is not a substructure of any tree)
function TreeNode(x) {
this.val = x;
this.left = null;
this.right = null;
}
// Determining whether a substructure is a substructure is similar to a preorder traversal
function isSubtree(root1,root2) {
if(! root2)return true;
if(! root1)return false;
if(root1.val ! == root2.val)return false;
return isSubtree(root1.left,root2.left) && isSubtree(root1.right,root2.right);
}
// Start from the root node and recursively determine whether there are substructures
function HasSubtree(pRoot1, pRoot2)
{
if(! pRoot1 || ! pRoot2)return false;
return (
isSubtree(pRoot1,pRoot2)
|| HasSubtree(pRoot1.left,pRoot2)
|| HasSubtree(pRoot1.right,pRoot2)
)
}
Copy the code
Operates on a given binary tree and transforms it into the mirror image of the source binary tree
function Mirror(root)
{
if(root === null) return root;
[root.left,root.right] = [root.right,root.left];
Mirror(root.left);
Mirror(root.right);
return root;
}
Copy the code
Input a binary tree to determine whether the binary tree is a balanced binary tree
1.Compare the height of the two subtrees, taking the maximum depth on both sides2.Check whether the height difference between the two subtrees is1
3.If more than1, then mark it as- 1(not an AVL tree), and then determine whether the subtree of the node is an AVL tree at each recursionfunction IsBalanced_Solution(pRoot)
{
returnorderTree(pRoot) ! = =- 1;
}
function orderTree(root) {
if(! root)return 0;
let left = orderTree(root.left);
let right = orderTree(root.right);
if(left === - 1 || right === - 1 || Math.abs(left-right) > 1) return - 1;
return Math.max(left,right)+1;
}
Copy the code
Find some paths to the binary tree
Path sum III
Given a binary tree, each node holds an integer value.
Finds the sum of paths equal to the total number of paths.
The path does not need to start at the root node or end at the leaf node, but the path direction must be downward (only from the parent to the child node).
The number of nodes in a binary tree cannot exceed 1000, and the value of the nodes is an integer ranging from -1000000 to 1000000.
function dfs(cur,sum,root,path,res){
cur += root.val;
path.push(root.val);
if(cur === sum && ! root.left && ! root.right){ res.push(path.slice(0));
}
root.left && dfs(cur,sum,root.left,path,res);
root.right && dfs(cur,sum,root.right,path,res);
path.pop();
}
var pathSum = function(root, sum) {
if(! root)return [];
let res = [],path = [],cur = 0;
dfs(cur,sum,root,path,res);
return res;
};
Copy the code
The path to a value in a binary tree
Enter a binary tree and an integer and print all paths where the sum of the node values in the binary tree is the input integer. A path is formed from the root of the tree down to the nodes through which the leaves pass.
// A path is defined as a path from the root of the tree down to the nodes passed by the leaves. (Note: In the list of returned values, the larger array is first)
1.DFS + back2.Search the path deeply, add the values of each node in the path, and the path is cached until the deepest traversal is reached3.Compares if the current value is the target value, if so adds the cached path to the result array, and if not falls back to the previous nodefunction dfs(root,expectNumber,cur,path,result) {
cur += root.val;
path.push(root);
if(cur === expectNumber && root.left === null && root.right === null){
result.push(path.slice(0));
}
root.left && dfs(root.left,expectNumber,cur,path,result);
root.right && dfs(root.right,expectNumber,cur,path,result);
/ / important
path.pop();
}
function FindPath(root, expectNumber)
{
let result = [],path = [],cur = 0;
if(! root)return result;
dfs(root,expectNumber,cur,path,result);
return result;
}
Copy the code
The maximum sum of paths in a binary tree
Given a non-empty binary tree, return its maximum path sum.
In this case, a path is defined as a sequence from any node in the tree to any node. The path contains at least one node and does not necessarily pass through the root node.
var maxPathSum = function(root) {
let max = -Infinity;
function dfs(root){
if(! root)return 0;
let l = Math.max(dfs(root.left),0);
let r = Math.max(dfs(root.right),0);
max = Math.max(max,l + r + root.val);
return Math.max(l,r)+root.val;
}
dfs(root);
return max;
};
Copy the code
other
The number of different binary index trees
Catalan number DP [0] = 1
dp[i] = dp[i- 1] * (4 * i + 2) / (i + 2);
var numTrees = function(n) {
if(! n)return 0;
let dp = [1];
for(let i = 1; i < n; i++){ dp[i] = dp[i- 1] * (4 * i + 2) /(i + 2);
}
return dp[n- 1];
};
Copy the code
Output an array in a reasonable packaging order according to the js dependency tree.
function resolve(tree){
let len = tree.require.length,queue = [];
for(let i = 0; i < len; i++){ queue.push([]); } tree = flatten(tree);let head = tree.name;
for(let key in tree){
let k = Number(key.slice(8.9));
Object.keys(tree[key]).length && queue[k].push(tree[key])
}
let res = [];
for(let i = queue.length- 1; i >=0; i--){for(let j = queue[i].length- 1; j >=0; j--){ res.indexOf(queue[i][j]) ===- 1&& res.push(queue[i][j]); }}return res;
}
function flatten(input) {
let res = {};
let re = function(obj,key){
if(obj instanceof Object && !(obj instanceof Array)) {let empty = true;
for(let i in obj){
re(obj[i],key ? `${key}.${i}` : i)
}
if(empty && key){ res[key] = {}; }}else if(obj instanceof Array) {if(obj.length){
for(let i = 0; i < obj.length; i++){ re(obj[i],key ?`${key}[${i}] ` : i)
}
}else{ res[key] = []; }}else{
if(obj ! = =undefined&& obj ! = =null){ res[key] = obj; }}}; re(input,' ');
return res;
}
var tree1 = {
name: 'main.js'.require: [{
name: 'A.js'
}, {
name: 'B.js'}}]var tree2 = {
name: 'page.js'.require: [{
name: 'A.js'.require: [{
name: 'B.js'.require: [{
name: 'C.js'}}]]}, {name: 'D.js'.require: [{
name: 'C.js'
}, {
name: 'E.js'
}]
}] }
resolve(tree1) // ['A.js', 'B.js', 'main.js']
resolve(tree2) // ['C.js', 'E.js', 'D.js', 'B.js', 'A.js', 'page.js']
Copy the code
Enter an array of integers and determine whether the array is the result of a sequential traversal of a binary search tree. If Yes, output Yes, otherwise output No. Assume that any two digits in the input array are different from each other.
1.The root node is the last node traversed in the sequential order2.The right subtree of a binary index tree is larger than the root node, and the left subtree is smaller than the root node, so the tree can be divided into two subtrees by the root node3.The subtree of the binary index tree is also a binary index tree, so judge the subtree separately until the last node is traversedvar verifyPostorder = function(postorder) {
if(! postorder.length)return true;
let tail = postorder.pop();
let key = postorder.length;
for(let i = 0; i < postorder.length; i++){if(postorder[i] > tail){
key = i;
break; }}for(let i = key+1; i < postorder.length; i++){if(postorder[i] < tail){
return false; }}return verifyPostorder(postorder.slice(0));
};
Copy the code
Enter a binary search tree and convert it into a sorted bidirectional linked list
var treeToDoublyList = function(root) {
if(! root)return null;
let head = null,tail = null,pre = null;
function dfs(root){
if(! root)return null;
dfs(root.left);
// The first node is the head node
if(! pre) head = root;// Points the pointer to the current node
else pre.right = root;
// Point the pointer to the previous node
root.left = pre;
// Update the last node
pre = root;
// Update the tail node
tail = root;
dfs(root.right);
}
dfs(root);
// End to end
head.left = tail;
tail.right = head;
return head;
};
Copy the code
The binary tree expands to a linked list
Preorder traversal, put the right subtree behind the right leaf node of the left subtree, put the left subtree into the right subtree, and leave the left subtree emptyvar flatten = function(root) {
function dfs(root){
if(! root)return;
dfs(root.left);
dfs(root.right);
let pre = root.left;
if(pre){
// Get the rightmost leaf node of the left subtree
while(pre.right){
pre = pre.right;
}
// Place the right subtree behind the right-most right subnode of the left subtree
pre.right = root.right;
// Place the newly constructed left subtree on the right subtree
root.right = root.left;
// Leave the left subtree empty
root.left = null;
}
}
dfs(root);
return root;
};
Copy the code
Hash table
There are often better solutions to interview problems that can be solved with Hashmap, but hashmap is one of the easiest to think of and write about
The daily temperature
Based on the daily temperature list, create a new list where the output is how much longer to wait for the temperature to rise beyond that day. If it does not rise after that, replace it with a zero.
For example, given a list of temperatures = [73, 74, 75, 71, 69, 72, 76, 73], your output should be [1, 1, 4, 2, 1, 1, 0, 0].
Tip: The length range of the temperature list is [1, 30000]. Each temperature value is in degrees Fahrenheit, an integer in the range of [30, 100].
var dailyTemperatures = function(T) {
let res = [],len = T.length;
while(len--){
res.push(0);
}
for(let i = 0; i < T.length; i++){for(let j = i+1; j < T.length; j++){if(T[j] <= T[i]){
res[i]++;
if(j === T.length- 1) res[i] = 0;
}else{
res[i]++;
break; }}}return res;
};
Copy the code
Groups of ectopes
Given an array of strings, group alphabetic ectopes together. An ectopic word is a string of characters with the same letters but different arrangements
var groupAnagrams = function(strs) {
if(! strs.length)return [];
let str = strs.slice(0),res = [];
strs = strs.map(x= > x.split(' ').sort().join(' '));
let map = new Map(a);for(let i = 0; i < strs.length; i++){ map.hasOwnProperty(strs[i]) ? map[strs[i]].push(str[i]) : (map[strs[i]] = [str[i]]); }for(let key in map){
res.push(map[key]);
}
return res;
};
Copy the code
Sum is a subarray of K
Given an array of integers and an integer **k, ** you need to find the number of consecutive subarrays of that array and k
var subarraySum = function(nums, k) {
if(! nums.length)return 0;
let res = 0;
for(let i = 0; i < nums.length; i++){let cur = 0;
for(letj = i; j < nums.length; j++){ cur += nums[j];if(cur === k) res++; }}return res;
};
Copy the code
The first K high frequency elements
Given a non-empty array of integers, return the elements that occur k above the frequency of occurrence
var topKFrequent = function(nums, k) {
if(! nums.length)return [];
let map = new Map(a);for(let i = 0; i < nums.length; i++){ map.has(nums[i]) ? map.set(nums[i],map.get(nums[i])+1) : map.set(nums[i],1);
}
let values = [],res = [];
for(let [k,i] of map){
values.push(i);
}
values.sort((x,y) = > y-x);
values = values.slice(0,k);
for(let [k,i] of map){
if(values.indexOf(i) ! = =- 1){ res.push(k); }}return res;
};
Copy the code
All the numbers in an array of length n are in the range 0 to n minus 1. Some of the numbers in the array are duplicate, but I don’t know how many of them are duplicate. I don’t know how many times to repeat each number.
// Please find any duplicate number in the array. For example, if you input an array {2,3,1,0,2,5,3} of length 7, the corresponding output is the first repeating number 2.
function duplicate(numbers, duplication)
{
let map = new Map(a);for(let i = 0; i < numbers.length; i++){ map.has(numbers[i]) ? map.set(numbers[i],map.get(numbers[i]) +1) : map.set(numbers[i],1);
if(map.get(numbers[i]) > 1){
duplication[0] = numbers[i];
return true; }}return false;
}
Copy the code
Finds the first character that occurs only once in a string (0<= string length <=10000, all letters) and returns its position
// Return -1 if no (case sensitive).
function FirstNotRepeatingChar(str)
{
let map = new Map(a);for(let key of str){
map.has(key) ? map.set(key,map.get(key)+1) : map.set(key,1);
}
for(let [key,value] of map){
if(value === 1) return str.indexOf(key);
}
return - 1;
}
Copy the code
Count prime Numbers
Count all primes less than the non-negative integer n
Given the range n of values to be screened, find the prime numbers within SQRT (n), first sieve with 2, that is, leave 2, remove the multiples of 2; And then you take the next prime, which is a sieve of three, and you keep the three, and you get rid of the multiples of three; Then sieve the next prime number, 5, leaving 5, and removing multiples of 5; Over and over again
var countPrimes = function(n) {
let count = 0;
let signs = new Uint8Array(n);
for (let i = 2; i < n; i++) {
// If it is a prime number
if(! signs[i -1]) {
count++;
// Remove the NTH order of the current prime
for (let j = i * i; j <= n; j += i) {
signs[j - 1] = true; }}}return count;
};
Copy the code
Numbers containing only prime factors 2, 3, and 5 are called ugly
Returns the KTH ugliest number
// For example, 6 and 8 are ugly numbers, but 14 is not because it contains the prime factor 7. It's customary to think of 1 as the first ugly number. Find the NTH ugliest number in descending order.
1. 0- 6They're both ugly numbers, so just return their value2.Use t1-T32.3.5The number of common factors, each time take the smallest common factor value, the initial value is1
function GetUglyNumber_Solution(index)
{
if(index < 7) return index;
let res = [1];
let t2 = 0,t3 = 0,t5 = 0;
for(let i = 1; i < index; i++){ res[i] =Math.min(res[t2]*2,res[t3]*3,res[t5]*5);
res[i] === res[t2]*2 && t2++;
res[i] === res[t3]*3 && t3++;
res[i] === res[t5]*5 && t5++;
}
return res[index- 1]}Copy the code
The oldest string with no duplicate characters
Given a string, find the longest string that does not contain repeating characters.
var lengthOfLongestSubstring = function(s) {
if(! s.length)return ' ';
let sub = ' ',res = ' ';
for(let i = 0; i < s.length; i++){if(sub === ' '){
sub += s[i];
if(i === s.length- 1 && res.length < sub.length) res = sub;
}else{
if(sub.indexOf(s[i]) === - 1){
sub += s[i];
if(i === s.length- 1 && res.length < sub.length) res = sub;
}else{
if(sub.length > res.length) res = sub;
sub = sub.substr(sub.indexOf(s[i])+1) + s[i]; }}}return res.length;
};
Copy the code
The stack and queue
The stack meets first-in, second-out, and the queue meets first-in, first-out
Use two stacks to implement a queue, complete the Push and Pop operations of the queue. The element in the queue is of type int
1.Simulate with the incoming and outgoing stacks2.The incoming queue is all added to the push3.Out of the queue to check whether the stack is empty, if not empty, the top element of the stack out of the stack; If empty, all elements in the push are pushed off the stacklet in_stack = [],out_stack = [];
function push(value) {
in_stack.push(value);
}
function pop() {
if(! out_stack.length){while(in_stack.length > 0){
out_stack.push(in_stack.pop())
}
}else{
returnout_stack.pop(); }}Copy the code
Define a data structure for the stack. Implement a min function in this type to get the smallest element in the stack. (the time complexity should be O (1).
1.Use the auxiliary stack to store the minimum value2.When pushing the stack, check whether the element is the minimum value. If so, push the main and auxiliary stacks3.When exiting the stack, check whether the top element of the main stack is consistent with that of the auxiliary stack. If so, pop it up together// Note: make sure you don't call pop() or min() or top() on the stack when the stack is empty.
let stack1 = [],stack2 = [];
function push(value) {
if(value <= Math.min(... stack1) || stack1.length ===0){
stack1.unshift(value);
stack2.unshift(value);
}else{
stack1.unshift(value)
}
}
function pop() {
if(stack1.length > 0) {
if (stack1[0] === stack2[0]) {
stack1.shift();
stack2.shift();
} else{ stack1.shift(); }}}function top() {
if(stack1.length > 0) {
return stack1[0]; }}function min() {
if(stack2.length > 0) {
return stack2[0]; }}Copy the code
Maximum sliding window
Given an array nums and the size k of the sliding window, find the maximum value in all the sliding Windows.
1.Maintain a monotonous bidirectional queue2.The new element is compared with the element at the end of the queue, added directly if it is smaller than the end of the queue, and popped out of the end of the queue until the appropriate location of the element is found3.The first element in the bidirectional queue is added to the result each timevar maxSlidingWindow = function(nums, k) {
if (k === 0) return [];
const length = nums.length;
if (length === 0) return [];
const deque = [];
for (let i = 0; i < k; ++i) {
cleanDeque(deque, nums, i, k);
deque.push(i);
}
const res = [];
res.push(nums[deque[0]]);
for (let i = k; i < length; ++i) {
cleanDeque(deque, nums, i, k);
deque.push(i);
res.push(nums[deque[0]]);
}
return res;
};
function cleanDeque(queue, arr, cur, k) {
// If the bidirectional queue contains a number that is not in the sliding window, directly exit the queue
if (queue.length && cur >= k + queue[0]) {
queue.shift();
}
while (queue.length && arr[idx] > nums[queue[queue.length - 1]]) { queue.pop(); }}Copy the code
Valid parentheses
Given a string containing only ‘(‘, ‘)’, ‘{‘, ‘}’, ‘[‘, ‘]’, determine whether the string is valid.
A valid string must meet the following requirements:
The opening parenthesis must be closed with a closing parenthesis of the same type. The opening brackets must be closed in the correct order.
Open bracket pushes the stack, close bracket compares to the top of the stack to see if it matches, match pops the top of the stack, no matchreturn falseCheck whether the stack is emptyvar isValid = function(s) {
if(! s.length)return true;
let stack = [];
for(let i = 0; i < s.length; i++){if(s[i] === '(' || s[i] === '{' || s[i] === '['){
stack.unshift(s[i]);
}else{
if(s[i] === ') ') {if(stack[0= = ='(') stack.shift();
else{
return false; }}else if(s[i] === '] ') {if(stack[0= = ='[') stack.shift();
else{
return false; }}else if(s[i] === '} ') {if(stack[0= = ='{') stack.shift();
else{
return false; }}}}return stack.length === 0;
};
Copy the code
String decoding
Given an encoded string, return its decoded string.
The encoding rule is k[encoded_string], which indicates that the enCOded_string inside the square brackets is repeated exactly K times. Notice that k is guaranteed to be a positive integer.
You can assume that the input string is always valid; There are no additional Spaces in the input string, and the square brackets are always formatted as required.
In addition, you can assume that the original data does not contain numbers, and that all the numbers only represent the number of repetitives k, for example there will be no inputs like 3a or 2[4].
var decodeString = function(s) {
// Use two stacks to store the current state, one for the number of repetitives and the other for the cumulative string
let repetStack=[],resStack=[];
// Concatenation string
let resStr = "";
// Indicates the number of repetitions
let repet = 0;
/ / traverse s
for(let i=0; i<s.length; i++){let cur = s.charAt(i);
if(cur == '[') {// Press the current state on the stack
repetStack.push(repet);
resStack.push(resStr);
// Empty to prepare for the following accumulation
repet = 0;
resStr = "";
}else if(cur == '] ') {// Retrieve the value in the current stack, that is, the number of times the current string is repeated
let count = repetStack.pop();
// Generate a repeat string based on the number of repetitions, assign a value to temp, and concatenate resStr
let temp = "";
for(let i = 0; i<count; i++){ temp += resStr; }// Concatenate with the previous string
resStr = resStack.pop() + temp;
}else if(cur>='0' && cur<='9') {/ / repet accumulation
repet = repet*10 + (cur-'0');
}else{
// Character accumulationresStr += cur; }}return resStr;
};
Copy the code
Reconstruct the cohort based on height
Suppose you have a bunch of people standing in a line out of order. Each person is represented by an integer pair (h, k), where H is the person’s height and k is the number of people in front of the person whose height is greater than or equal to H. Write an algorithm to reconstruct the queue.
1.In ascending order of height, in ascending order of number of people of the same height2.Inserts each element of the queue in order into the index positionvar reconstructQueue = function(people) {
if(! people)return [];
people.sort((x,y) = >{
return x[0] === y[0]? x[1]-y[1] : y[0] - x[0];
});
let res = [];
for(let i = 0; i < people.length; i++){ res.splice(people[i][1].0,people[i]);
}
return res;
};
Copy the code
The infix expression is suffixed
// Add the number directly to the result
// The stack is empty and the operator is pushed directly onto the stack
// If you encounter an open parenthesis, push the stack directly. If you encounter a close parenthesis, add the top element of the stack to result and then bounce the stack. Loop until you encounter an open parenthesis, then bounce the open parenthesis
// When an operator is encountered, determine the priority of the operator and the elements at the top of the stack, bounce all the top of the stack whose priority is greater than or equal to that operator, and then push the operator
// Add the remaining characters in the stack to result
function toPoland(str){
let stack = [],result = ' ';
for(let i = 0; i < str.length; i++){if(!Object.is(Number(str[i]),NaN)){
result += str[i];
}else if(stack.length === 0 && Object.is(Number(str[i]),NaN)){
result += ' ';
stack.push(str[i]);
}else if(str[i] === '('){
stack.push(str[i])
}else if(str[i] === ') '){
result += ' ';
while(stack[stack.length- 1]! = ='('){
result += stack.pop();
}
stack.pop();
}else if(str[i] === The '*' || str[i] === '/') {while(stack[stack.length- 1= = =The '*' || stack[stack.length- 1= = ='/'){
result += ' ' + stack.pop();
}
result += ' ';
stack.push(str[i]);
}else if(str[i] === '+' || str[i] === The '-') {while(stack[stack.length- 1= = =The '*' || stack[stack.length- 1= = ='/' || stack[stack.length- 1= = ='+' || stack[stack.length- 1= = =The '-'){
result += ' ' + stack.pop();
}
result += ' '; stack.push(str[i]); }}while(stack.length){
result += ' ' + stack.pop();
}
return result;
}
Copy the code
Evaluate postfix expression
1.Digital into the stack2.Operator with the top of the stack as the right operand and the top of the secondary stack as the left operand3.Push the result of the operation onto the stack4.The last value of the stack is the resultfunction CalcRPN(str) {
let stack = [];
let num = ' ';
for(let i = 0; i < str.length; i++){if(str[i] === ' ') {if(num ! = =' ') stack.push(Number(num));
num = ' ';
}else if(!Object.is(Number(str[i]),NaN)){
num += str[i];
}else if(str[i] === '+') {let right = stack.pop();
let left = stack.pop();
stack.push(left + right);
}else if(str[i] === The '-') {let right = stack.pop();
let left = stack.pop();
stack.push(left - right);
}else if(str[i] === The '*') {let right = stack.pop();
let left = stack.pop();
stack.push(left * right);
}else if(str[i] === '/') {let right = stack.pop();
letleft = stack.pop(); stack.push(left / right); }}return stack.pop();
}
Copy the code
Enter two integer sequences. The first sequence represents the push order of the stack. Determine if the second sequence is likely to be the pop order of the stack. Suppose all the numbers pushed on the stack are not equal.
1.Simulate the stack process2.The variable push stack pushes the auxiliary stack one element at a time3.When determining whether the auxiliary stack is empty, the top element of the pop stack is the same as the top element of the auxiliary stack4.Finally, determine whether the auxiliary stack is empty// for example, sequence 1,2,3,4,5 is the push sequence of a stack. Sequence 4,5,3,2,1 is a popup sequence corresponding to the push sequence, but 4,3,5,1, and 2 cannot be the popup sequence of the push sequence.
// (Note: the lengths of the two sequences are equal)
function IsPopOrder(pushV, popV) {
let stack = [],k = 0;
for(let i = 0; i < pushV.length; i++){ stack.unshift(pushV[i]);while(stack[0] && popV[k] && stack[0] === popV[k]){ stack.shift(); k++; }}return stack.length === 0;
}
Copy the code
The KTH largest element in the array
// Priority queue. It's a little painful
var findKthLargest = function(nums, k) {
let queue = [];
for(let i = 0; i < nums.length; i++){if(queue.length < k) {
let pos = 0;
while(pos < k) {
if(queue[pos] === undefined) {
queue[pos] = nums[i];
break;
} else {
if(nums[i] > queue[pos]) {
queue.splice(pos,0,nums[i]);
break; } } pos++; }}else {
if(nums[i] > queue[k- 1]) {
let pos = 0;
while(pos < k) {
if(nums[i] > queue[pos]) {
queue.splice(pos,0,nums[i]);
queue.pop();
break; } pos++; }}}}return queue[k- 1];
};
Copy the code
The list
Reverse a linked list
function ReverseList(pHead)
{
// write code here
if(pHead === null || pHead.next === null) return pHead;
let pre = null,nex = null;
while(pHead ! = =null){
nex = pHead.next;
pHead.next = pre;
pre = pHead;
pHead = nex;
}
return pre;
}
Copy the code
Replication of complex linked lists
Implement a function that copies a complex linked list. In complex linked lists, each node has a next pointer to the next node and a random pointer to any node or null in the list.
function Clone(pHead)
{
// write code here
if(pHead === null) return pHead;
let p1 = pHead;
while(p1 ! = =null) {let node = new RandomListNode(p1.label);
node.next = p1.next;
p1.next = node;
p1 = node.next;
}
p1 = pHead;
while(p1 ! = =null) {let node = p1.next;
if(p1.random) node.random = p1.random.next;
p1 = node.next;
}
p1 = pHead;
let p2 = pHead.next;
while(p1.next ! = =null) {let node = p1.next;
p1.next = node.next;
p1 = node;
}
return p2;
}
Copy the code
Merge two ordered lists
Merge the two ascending lists into a new ascending list and return. The new list is formed by concatenating all the nodes of the given two lists
var mergeTwoLists = function(l1, l2) {
if(! l1)return l2;
if(! l2)return l1;
if(! l1 && ! l2)return null;
if(l1.val <= l2.val){
l1.next = mergeTwoLists(l1.next,l2);
return l1;
}else{
l2.next = mergeTwoLists(l1,l2.next);
returnl2; }};Copy the code
Circular linked list
Given a linked list, determine whether there are rings in the list
var hasCycle = function(head) {
if(! head || ! head.next || ! head.next.next)return false;
let fast = head.next.next,slow = head.next;
while(fast ! == slow){if(fast === null || fast.next === null) return false;
fast = fast.next.next;
slow = slow.next;
}
return true;
};
Copy the code
Circular linked list II
Given a linked list, return the first node where the list started to enter the loop. Null is returned if the list is loopless
var detectCycle = function(head) {
if(! head || ! head.next)return null;
let fast = head.next.next,slow = head.next,p1 = head;
while(fast ! = =null&& fast ! == slow){if(fast.next) fast = fast.next.next;
else fast = null;
slow = slow.next;
}
if(fast === null) return null;
else{
while(p1 ! == slow){ p1 = p1.next; slow = slow.next; }returnslow; }};Copy the code
Cross linked list
Write a program to find the starting node where two singly linked lists intersect
var getIntersectionNode = function(headA, headB) {
var pA = headA;
var pB = headB;
while(pA ! == pB){ pB = pB? pB.next: headA; pA = pA? pA.next: headB; }return pA;
};
Copy the code
Copies a linked list with random Pointers
Given a linked list, each node contains an additional random pointer that can point to any node or null node in the list
var copyRandomList = function(pHead) {
if(pHead === null) return pHead;
let p1 = pHead;
while(p1 ! = =null) {let node = new Node(p1.val);
node.next = p1.next;
p1.next = node;
p1 = node.next;
}
p1 = pHead;
while(p1 ! = =null) {let node = p1.next;
if(p1.random) node.random = p1.random.next;
p1 = node.next;
}
p1 = pHead;
let p2 = pHead.next;
while(p1.next ! = =null) {let node = p1.next;
p1.next = node.next;
p1 = node;
}
return p2;
};
Copy the code
string
Letters for telephone numbers
Given a string containing only the numbers 2-9, return all the combinations of letters it can represent.
Give the mapping of numbers to letters as follows (same as telephone keys). Note that 1 does not correspond to any letter.
// This backtrace is very clever. It is explained in lc
var letterCombinations = function(digits) {
if(! digits)return [];
let map = {
'2': 'abc'.'3':'def'.'4':'ghi'.'5':'jkl'.'6':'mno'.'7':'pqrs'.'8':'tuv'.'9':'wxyz'
};
let res = [];
function dfs(index,path) {
if(index === digits.length) {
res.push(path);
return;
}
for (let i = 0; i < map[digits[index]].length; i++) { path += map[digits[index]][i]; dfs(index+1,path.slice());
path = path.slice(0, path.length- 1);
}
}
dfs(0.' ');
return res;
};
Copy the code
Back to the text string
Given a string, your task is to calculate how many substrings there are in the string.
Substrings with different start or end positions are counted as different substrings, even if they consist of the same characters.
var countSubstrings = function(s) {
let s2 = s.split(' ').reverse().join(' ');
let sum = 0;
const len = s.length;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j <= len; j++) {
if (s.substr(i, j - i) === s2.substr(len - j, j - i)) {
sum += 1}}}return sum;
};
Copy the code
Parentheses generates
The number N represents the logarithm that generates parentheses. Design a function that generates all possible and valid parentheses combinations
var generateParenthesis = function(n) {
if(! n)return [];
let res = [];
function dfs(subs,left,right,n){
if(left === n && right === n){
res.push(subs);
return;
}
if(left < right){
return;
}
left < n && dfs(subs+'(',left+1,right,n);
right < n && dfs(subs+') ',left,right+1,n);
}
dfs(' '.0.0,n);
return res;
};
Copy the code
Longest common prefix
Write a function to find the longest common prefix in an array of strings.
Returns an empty string “” if no common prefix exists
var longestCommonPrefix = function(strs) {
if(! strs.length)return ' ';
strs.sort();
let a = strs[0],b = strs[strs.length- 1],res = ' ';
for(let i = 0; i < a.length; i++){if(i < b.length && a[i] === b[i]){
res += a[i];
}else break;
}
return res;
};
Copy the code
Password decryption
Xiao Ming got a password table from the boss there, saying that if unlock the secret in the password table, can be promoted pay rise, win white rich beauty, towards the peak of life. The password table is a CSV file with data consisting of numbers (without decimal points) and letters. Xiao Ming needs to extract the numbers in each data (for example, 1a2b3c is extracted to obtain 123, and the whole extracted number is treated as a decimal number), and add up the items with odd numbers to solve the mystery. Please implement a function sum to help Xiao Ming complete this work.
function sum(input: string) {
return input.split(/[,\n]/)
.map(item= > Number(item.replace(/[a-z]/ig."")))
.filter(num= > num % 2= = =1)
.reduce((a, b) = > a + b)
}
Copy the code
Parse url parameters into objects
function parseUrl(url){
url = decodeURIComponent(url);
let strs = url.slice(url.indexOf('? ') +1).split('&');
return strs.reduce((x,y) = >{
let key = y.split('=') [0];
let value = Object.is(Number(y.split('=') [1]),NaN)? y.split('=') [1] : Number(y.split('=') [1]);
x[key] = value;
returnx; }, {}); }Copy the code
Implement the template engine
const template = 'there are ${count} ${name} on the ${place}.';
function parse(template,obj){
let reg = /\$\{((\w|_|\$)*)\}/g;
let keys = template.match(reg).map(x= > x.slice(2,x.length- 1));
let value = keys.map(i= > obj[i] === undefined ? ' ' : String(obj[i]));
return template.replace(reg,()=> value.shift());
}
console.log(parse(template, {count: 2.name: 'apples'.place: 'table'}, create));
//there are 2 apples on the table.
Copy the code
HTML any tag string into a JSON file
Fixed the previous error code, the overall idea is as follows:
- Remove the HTML string from <> and process it into an array
- Extract the tree structure
- Convert the tree structure to JSON
const str1 = '<div>1<span>2<a>3</a>4</span>5<span>6<a>7</a>8<a>9</a>10</span>11</div>';
function Dom2JSON(str) {
str = str.split('<').map(x= > x.split('>'));
let res = [],stack = [],temp = {},cur = {},key = 0;
// Get the tree structure
for(let i = 1; i < str.length; i++) {if (str[i][0].indexOf('/') = = =- 1) {
temp = {};
temp['key'] = key++;
temp['tag'] = str[i][0];
temp['value'] = str[i][1];
temp['children'] = [];
temp['parent'] = stack.length === 0 ? 0 : stack[0] ['key'];
stack.unshift(temp);
} else {
cur = stack.shift();
// The stack is empty when the current element is the root elementstack.length ! = =0 && (stack[0] ['value'] = stack[0] ['value'] + cur['value'] + str[i][1]); res.unshift(cur); }}// Make the traversal index match the key value
res = res.sort((x, y) = > x['key'] - y['key']);
for (let i = res.length - 1; i >0; i--) { temp = {}; temp['tag'] = res[i]['tag'];
temp['value'] = res[i]['value'];
temp['children'] = res[i]['children'];
res[res[i]['parent']] ['children'].unshift(temp);
}
res = res[0];
delete res['parent'];
delete res['key'];
return JSON.parse(JSON.stringify(res));
}
console.log(Dom2JSON(str1));
}
// The conversion results are as follows
// let res ={
// tag: "div",
// value: "1234567891011",
// children: [
/ / {
// tag: "span",
// value: "234",
// children: [
/ / {
// tag: "a",
// value: "3",
// children: [],
/ /}
/ /,
/ /},
/ / {
// tag: "span",
// value: "678910",
// children: [
/ / {
// tag: "a",
// value: "7",
// children: [],
/ /},
/ / {
// tag: "a",
// value: "9",
// children: [],
/ /}
/ /]
/ /}
/ /]}
Copy the code
reference
Backtracking template passes Leetcode
Eight sorting, each show their abilities – GIF
Eight sorting classic algorithm (diagram + reference source code)
Front-End-Interview-Notebook
Super love and check set ~
Getting Started with topological Sorting (really easy)
One method eliminates six stock problems
leetcode