An array is a collection of data of the same type stored in a continuous memory space.

Array can easily obtain the corresponding data under the subscript by means of subscript index.

Take an example of a character array, as shown in the figure:

## Binary search:

The premise of the algorithm is that the array is an ordered array. At the same time, the title also emphasizes that there are no duplicate elements in the array, because once there are duplicate elements, the element subscripts returned by the binary search method may not be unique. These are the preconditions for using the dichotomy. When you see that the Title Description meets the above conditions, you can think about whether the dichotomy can be used.

Writing dichotomy is often messy, mainly because the definition of interval is not clear, and the definition of interval is invariant. To keep invariants in the process of binary search is to insist on operating according to the definition of interval every time the boundary is processed in while search, which is the cyclic invariants rule.

Loop invariants: in the process of while or for, many are executed repeatedly, such as the judgment in while and for. In many cases, the judgment condition is inequality, and the cyclic invariant includes interval. For example, the [,) interval includes the right boundary, and the right boundary is not included in each judgment. If the right boundary is the value that needs to be added to the judgment, it can not be written in this way.

java version dichotomy writing method (left closed right closed):

class Solution { public int search(int[] nums, int target) { // Avoid multiple loop operations when target is less than num [0] num [num.length - 1] if (target < nums[0] || target > nums[nums.length - 1]) { return -1; } int left = 0, right = nums.length - 1;//right is the last numeric value of the contained num while (left <= right) {//Because the right boundary is included, the right boundary needs to be judged, so the judgment condition is<= int mid = left + ((right - left) >> 1); if (nums[mid] == target) return mid; else if (nums[mid] < target) left = mid + 1;//If + 1 is required, the intermediate value must not meet the conditions, so it has been judged else if (nums[mid] > target) right = mid - 1; } return -1; } }

## Delete array element (double pointer)

Maybe I said, delete the redundant elements.

You should know that the elements of the array are continuous in the memory address. You can't delete an element in the array alone, but can only overwrite it.

The form of double pointer: 1. The fast pointer has a large span of steps than the slow pointer, for example, slow one step at a time and fast two steps at a time; solve the circular entry of the linked list

2. Pointer A and pointer B move from both sides to the middle. For example, the following example is the ordered square sorting problem with negative numbers

3.fast is one step ahead of slow. fast goes step by step. Slow meets the conditions and then goes. fast is a Pathfinder. Slow is modified. It is characterized by deleting array elements

There are many forms, and more practice is needed.

class Solution { public int removeElement(int[] nums, int val) { // Speed pointer int fastIndex = 0; int slowIndex; for (slowIndex = 0; fastIndex < nums.length; fastIndex++) { if (nums[fastIndex] != val) { nums[slowIndex] = nums[fastIndex]; slowIndex++; } } return slowIndex; } }

## Ordered square reordering with negative numbers

Generally, if the whole row is arranged, use fast row, and then square the time complexity n × log(n) + n

However, after using the double pointer, open up A storage place in the memory, compare the square size of A and B from both ends, and put the larger one in the newly opened place. At the same time, let the larger pointer move. You can do it on the side of the comparison and cycle. The time complexity is n

class Solution { public: vector<int> sortedSquares(vector<int>& A) { int k = A.size() - 1; vector<int> result(A.size(), 0); for (int i = 0, j = A.size() - 1; i <= j;) { // Note that I < = J is required here, because the last two elements need to be processed if (A[i] * A[i] < A[j] * A[j]) { result[k--] = A[j] * A[j]; j--; } else { result[k--] = A[i] * A[i]; i++; } } return result; } };

## As soon as the spiral matrix is written:

Always remember the principle of loop invariance. Follow the circle of the square, and each time it is closed on the left and open on the right. Each time, you need to update the initial node and the length n

Simulate the process of drawing the matrix clockwise:

- Fill up from left to right
- Fill the right column from top to bottom
- Fill down from right to left
- Fill left column from bottom to top

From outside to inside, circle by circle.

It can be found that there are many boundary conditions here. In a cycle, if so many boundary conditions are not traversed according to fixed rules, it is a cycle as deep as the sea. From then on, the offer is a passer-by.

When we draw a circle here, we should draw every four edges. How to draw these four edges? Each edge should adhere to the consistent principle of left closing and right opening, or left opening and closing, so that this circle can be drawn according to the unified rules.

class Solution { public int[][] generateMatrix(int n) { int[][] arr = new int[n][n]; int t = 1,mid = 0; int loop = n/2; int counter = 1; if(n%2 == 1){ arr[n/2][n/2] =n*n; } int startx = 0 ,starty = 0; while(loop > 0){ for(int x =startx,y = starty;y<starty + n-1;y++){ arr[x][y]=counter; counter++; } for(int y = starty + n - 1,x=startx;x <starty + n-1;x++){ arr[x][y]=counter; counter++; } for(int x = startx + n - 1,y=starty + n-1;y>startx;y--){ arr[x][y]=counter; counter++; } for(int y = starty,x=startx + n-1;x>startx;x--){ arr[x][y]=counter; counter++; } startx++; starty++; loop--;n=n-2; } return arr; } }