LeetCode Doing Questions

Self notes

Encountered some problems when doing the questions, or learned something

11.01

The difference between offer and add in
Queue add() and offer() in Queue are both used to add an element to the queue.
In the case of full capacity, the add() method will throw an IllegalStateException, and the offer() method will only return false.

Expansion to the difference
in Queue For Queue, it is a FIFO (first in first out) queue. Adding elements can only be at the end of the queue, and removal can only be at the head of the queue.
For this group of methods, success returns true, and an exception is thrown when the operation fails. This is the main difference from the following group of methods.
add(E e): add an element to the end of the queue
remove(): get the element at the head of the team and remove it from the queue
element(): get the element at the head of the team, but do not remove
this group from the queue , success Return true, return a special value (depending on the operation, NULL or false) on failure, the offer (E e) operation is designed for capacity-constrained queue implementations; in most implementations, the insert operation will not fail .
offer(E e): add an element to the end of the queue
poll(): get the element at the head of the queue and remove it from the queue
peek(): get the element at the head of the queue, but not remove it from the queue

Pre-order, middle-order, post-order
, are named by the location visited by the root node (current node), and they are all implemented with dfs.
Front order: middle left and right
middle order: left middle right
back order: left and right middle

11.02

Morris traversal algorithm
simulates recursive popping by setting clues, thereby trading a certain time complexity for the space complexity of o(1).
Among them, the in-order traversal is used more. Post-order traversal is more difficult, I haven't figured it out yet.

11.3

How to get the minimum value of the current index.
Learned from the stack problem getmin, maintain a minimum stack. For each element inserted, it is compared with the current minimum value. The smaller one is pushed onto the stack and the minimum value is updated. Thus, a minimum value under the current index can be obtained.

Learned the monotonic stack from the daily temperature.
In fact, the monotonic stack is to find the numbers on the left and right sides that are larger or smaller than you and the time complexity is O(N).
As the name implies, the stack is monotonous, and it can judge the left ( (Right) Which one is bigger (smaller) than you first? At the same time, the time complexity is low.

Initializing the array
For the int type array, it is very troublesome to initialize it, so Baidu has a method:, the Arrays.fill(arr, value);actual measurement is available, but the speed is unknown, and I didn’t look at the source code.

When Deque and Stack were
doing questions, I saw comments recommend Deque instead of Stack, saying that Stack is inefficient.
So I searched.
For Stack, it is inherited from the Vector class. Vector and ArrayList, LinkedList are juxtaposed to implement the List interface. It is implemented internally by an array and supports thread synchronization, that is, only one thread can write to a Vector at a time, avoiding inconsistencies caused by multiple threads writing at the same time, but synchronization requires a high cost, so its access is slower than ArrayList.
For Deque, it is a subinterface of Queue, and it has two implementation classes, ArrayDeque and LinkedList. It can act as a stack or a queue. When acting as a stack, use the push and pop methods of ArrayDeque. When acting as a queue, use the add and remove methods of ArrayDeque.
(Regarding speed, I tried it, and the instant time rose from 58% to 95%, which is indeed much faster. Good things and good things, I will use Deque in the future)

11.6

I didn't learn the new stuff the day before yesterday. I just got a small code. I was very busy these two days to catch up with the workload of the group meeting.
Check the collection
here, mark it first, and there is also at the end of the list of questions. If you see a blog that is particularly fun to check the collection, please record it first
https://blog.csdn.net/qq_41593380/article/details/81146850

11.8

Learned the manacher algorithm, and attached my own ide blog post address. https://blog.csdn.net/qq_34687559/article/details/109560059
Regarding manacher, there are actually many scenarios that can be used, and I will not deal less with it in the future.
The second is the concept of symmetry, which can be kept in mind. Symmetry can reduce complexity.

11.9

I watched it scattered for a day, and there were too many trivial matters, all of which were irrelevant and irrelevant to me. Fortunately, in the end, I basically understood the kmp algorithm, and then I wanted to write it out.
The kmp algorithm can also be regarded as using the point of symmetry. In the string, symmetry is really used in many places.
However, I also saw ac automata in the process of looking through the information. It is a multi-mode character search (kmp is a single-mode character search, and kmp is the basis of ac automata). Mark it first, if you have a chance to contact it in the future Go take a good look.

11.10

Ordered matrix (rows and columns meet a certain ascending or descending order) I
did the problem 240. This is a sorted matrix, increasing from left to right, and increasing from top to bottom. Regarding this problem, the violent solution, dfs is replaced by stack It's okay to solve it, but starting from the lower left corner, iteratively searching is easy. The reason is that
the key to this algorithm is to find a suitable starting point for traversal. This point must have some particularity. In this two-dimensional matrix, the four corners are four special points, but their characteristics are different. The upper left and lower right are matrices. The minimum and maximum values ​​of, the lower left and upper right have two sides, if it is the maximum value of the row, it is the minimum value of the column, and vice versa. When the upper left and lower right are not equal to the target value, the next step can be to traverse rows or columns. It is uncertain, while the lower left and upper right can be determined because the characteristics of its own value can exclude a path in one direction, and there is only one Traverse the path. (I read the comments, I feel great)
For this kind of matrix and similar questions, we must mainly find its special points and analyze the meaning of their special points.
This question can be said to have taught me a new way of thinking.

About
Merge Sort Understand that merge sort is actually a process of branch + double pointer comparison and merging.
Generally speaking, for two ordered arrays (or linked list or whatever) to merge, just use double pointers (this means).
In many cases, we need to merge multiple ordered arrays in an orderly manner. At this time, we can't expect this to be merged with pointers, variables, or something, so at this time, a very useful data structure is preferred. Queue, use priority queue for a comparison, special convenience, especially comfortable. Here, a comparator needs to be established in java.
Then for the array, you can choose to put the array in the queue. The first element of the array is the value, and the last two are the coordinates. Comparators also compare prices with numerical values. This is very convenient. You can put as many as you want into the priority queue, and you don't need to put all of them, which wastes time and complexity.

11.15

The
maximum function of the combined check is to check whether there is a ring in the graph. The
basic principle is that every time the connected piece is maintained, when the two ends of the newly appearing edge are both in the connected piece, a circle is formed.
The difficulty lies in the realization of the Disjoint set.
Clearly, regarding the realization of Disjoint set, this is indeed very interesting.
Use an array to record the parent node of each point. In this way, if you keep going up, you can find the topmost parent node. If the parent node is the same, it means that the two nodes are connected.
That is, the basis for judging the connection becomes whether there is the same parent node.
The two main functions implemented are find_root and union.
Regarding optimization, because it is equivalent to connecting a tree, the depth of the tree may be too deep, so each time find_root will be very large, so you can consider reducing the height of the tree, a common parent node, and then many child nodes. In this case, you only need to find_root once every time. Of course, this is very troublesome to achieve. There is a method that is easier to implement and has a small overhead.
Add a tree with a low depth to a tree with a high depth so that the depth of the overall tree will not change too much. Here, my idea is to return from find_root and return an array, the 0th position is root, and the 1st position is the depth (the number of finds).

11.16

See also the horse-drawn cart algorithm, question 5, just change it at will.

Int and long In
java, int is 4 bytes, and long is 8 bytes.
In the processing of int, in many cases it may cause the data of the basic type of int to actually exceed 4 bytes, and it will overflow at this time.
There are several ideas when dealing with overflow.
Idea 1: Use long to avoid overflow, and judge after the final calculation (int)res==res to see if it overflows
Idea 2: Catch the exception, and then perform the corresponding processing

	public int reverse(int x) {
    
    
        String xString = Integer.toString(x);
        String string = xString;
        int flag = 1;
        if (x < 0) {
    
    
            flag = -1;
            string = xString.substring(1);
        }
        try {
    
    
            return Integer.valueOf((new StringBuilder(string)).reverse().toString()) * flag;
        }catch (Exception e){
    
    
            return 0;
        }
    }

Idea 3: For questions like leetcode 07, you can determine whether the value of the previous iteration is equal to the value of the previous iteration after each calculation of self/10 in the iteration, so as to determine whether it overflows.
eg:

class Solution {
    
    
    public int reverse(int x) {
    
    
        int result = 0;
        while(x != 0) {
    
    
            int tmp = result; // 保存计算之前的结果
            result = (result * 10) + (x % 10);
            x /= 10;
            // 将计算之后的结果 / 10,判断是否与计算之前相同,如果不同,证明发生溢出,返回0
            if (result / 10 != tmp) return 0; 
        }

        return result;
    }
}

11.17

Finite state machine
Good guy, good guy, I'm a good guy directly, it can help reduce the possibility of if-else errors, but the usage is still not much, and it is actually necessary to analyze it carefully.

The string is repeated several times

String.join("",Collections.nCopies(quotient,str[start]))

But this is actually very slow, convenient, but inappropriate

11.18

Double pointer and hashset
in the case of allowing sorting, the double pointer solves the sum of two numbers, and the efficiency of the sum of three numbers is higher than that of hashset, although it is a time complexity.

Sorting
When watching the sorting video, choosing sorting feels like the opposite of bubbling.
Insertion sort, just like playing cards, insert each time.
For classic quick sort, every time you make a selection, use the last number X as the criterion, and divide the array into <=X and >X.
The improved quick sort is that: in the classic sort, only one number can be determined each time, which is our last number X, but the problem is that there is not only one X, there may be many Xs. Therefore, the improved X of X hopes to determine all the Xs. This is very important.
The reason for random fast sorting is that the previous fast sorting depends on the last element X. This X may be extremely unstable. Each division is uneven, because it is only when the array can be divided evenly in half. The best, but we can’t be sure at all, so in the end, we can only choose X in a random way. Of course, this will be better than the last position, but in essence, it’s the same, because both It is random, and the probability is the same.
After reading the sorting here, write a blog to summarize it, because in fact, I learned it a long time ago, but now I’m just reviewing it, and I’ve read it many times, but I still have to summarize it to make sure, I can’t read it every time, it’s a waste of time. Up.
Random quick sorting is a very fast sorting algorithm with low time complexity. Because of its simple implementation and low constant terms, it is generally used.

11.19

Heap
has a deeper understanding of the heap, including the heap is composed of arrays, which is a virtual illusion structure, realized through the mapping of arrays, and its virtual structure is a complete binary tree.
It can solve the problem of continuous flow median (big root pile and small root pile to divide the data), and it is also very important in greedy.
Heap sorting
is to build a heap (big root), and then pop the top of the heap each time (the top of the heap is exchanged with the end of the heap, and then the size of the heap is reduced by 1), so that the current maximum number is guaranteed to be placed behind each time, and n-1 Once popped up, you can get an ascending sequence.
Reverse
seems to be that there is no way to reverse the array in Java, so it is a little troublesome. If it is ordered, you can use sort to solve it. If not, write 4 lines of code honestly to exchange O(mid) reverse. .
sort
Arrays.sort(nums,0,i) can achieve a certain range of sorting in the array, which is super easy to use.

11.26

Lexicographical string

	char[] chars = str.toCharArray();
    Arrays.sort(chars);
    String key = new String(chars);

List to array The
size of the array must be specified so that the conversion can be carried out

return res.toArray(new int[res.size()][2]);

List cannot be cloned.
Because of the problem of deep copy, there is often a returned data structure of List<List>, but List cannot be cloned, so you can sample the following methods to copy and new a List,

List<Integer> temp = new LinkedList<>(res.get(j));

01.01

I didn’t write this blog before because I didn’t encounter minor
problems in the middle. The questions were also brushed normally, and I brushed a lot, and the project went well. I
originally wanted to open a new one to record it. Forget it, let’s just write it here.

Continuous array copy
java provides a method to copy the continuous substring of an array to an array of zero

		int[] nums1 = new int[nums.length-1];
        System.arraycopy(nums,0,nums1,0,nums.length-1);
        int[] nums2 = new int[nums.length-1];
        System.arraycopy(nums,1,nums2,0,nums.length-1);

For example, the System.arraycopy() method used in the above code is a native method that is fast to execute. It is recommended to use
the method parameters as (source array, starting copy position, target array, starting paste position, copy length ), where the length of the target array should be greater than or equal to the copy length

Guess you like

Origin blog.csdn.net/qq_34687559/article/details/109367926