leetcode brush Title records day024:20 and 118

20. Easy to use: 45% pass rate

Method 1: Origin: Failed Violence: For my own future review, there are all kinds of situations that I did not think of at first but follow up and corresponding responses

Principle: Normally judge if the current item and the next item are a bunch of parentheses, and add the response of the left parentheses group (e.g.'{{}}')
Failure point: The code below'([]){}'will judge true as false
HashMap related knowledge website:https://m.runoob.com/java/java-hashmap.html?ivk_sa=1024320u

class Solution {
    public boolean isValid(String s) {
        int len = s.length();
        if(len<=1){
            // As the case'{'
            return false;
        }
        
        // To create a hash table, note that the hash table cannot be of the original type, such as char, and needs to be encapsulated with classes such as Character
        Map<Character, Character> yes = new HashMap<Character, Character>();
        yes.put('{', '}');
        yes.put('[', ']');
        yes.put('(', ')');
        
        // The following are described in the for loop
        int left = 0;
        int right = 0;
        int end = 0;
        boolean bool = true;
        boolean boolStart = false;

        // i self-incremental criteria definition at the end of each cycle, not written here
        for(int i = 0; i < len;){
            // As in case'][]','()][]'
            if(!yes.containsKey(s.charAt(i))){
                return false;
            }
            // If the left bracket group event starts,'{[]}'as in'{[]}', then if i=1 the following if determines i+=2 and continue s
            // Open the next loop directly, and then go through the if again, when i=len-1, the call to s.charAt(i+1) overflows
            // So add i+1 <len && in front so that the current if ends before overflow 
            if(i+1<len && yes.get(s.charAt(i)) == s.charAt(i+1)){
                i+=2;
                // There are two possibilities for matching parentheses:
                // 1. Groups without open parentheses in front: e.g. ({[]})
                // 2. Groups preceded by left brackets: e.g. ()[]{}, ({[]}){}
                if(!bool){
                    // If there are left bracket groups in front
                    // That means you can start matching the left bracket group
                    boolStart = true;
                    // Right bracket group start subscript
                    right = i; 
                    // Subscript used to terminate group matching of left and right parentheses, that is, the left parentheses subscript of the current pair of parentheses
                    end = i-2;
                } else {
                    // In the case () {[]}[], when i=5 is the first right bracket in the right bracket group
                    // If continue is not written in else, it goes directly into the next loop.
                    // Enter this if judgment} and [Is it a match?
                    // But hashmap doesn't have a key}, which is an error, so we should skip continue after entering the right bracket group
                    // Enter the for loop in if(boolStart) {below
                    continue;
                }
                // As in case'([]){'
                if(i+1 == len-1){
                    return false;
                }
             
		   // The response, such as'{[]}', works the same as if above
            }else if(i+1<len && !yes.containsKey(s.charAt(i+1))){
                // If the current element and the next element do not form parentheses
                // And the next element is not {, (, [such left parentheses then false is returned
                return false;

            }else if(bool){
                // The above situations can handle situations such as'()[]{}','(]', etc.
                // The following is for'{[]}' 
                // You can see that this situation is characterized by the occurrence of one or more left parentheses (the left parentheses at the beginning of the marker)
                // There must be a pair of parentheses
                // Once the bracket appears, the first subsequent right bracket must match the opening left bracket

                // Turn off if to protect the left value before ending the current left bracket event
                bool = false; 
                left = i;
            }

            if(boolStart){
                for(; left < end; left++,right++){
                    if(right == len){
                        return false;
                    }
                    if(!(yes.get(s.charAt(left)) == s.charAt(right))){
                        return false;
                    }
                }
                // The left bracket group and the right bracket group are paired, and if for the left bracket group can be reopened
                bool = true;
                // Since the right bracket group is also detected, the subscript for i jumps directly to the next item in the right bracket
                if(right == len-1){
                    return true;
                } else {
                    i = right;
                }
            } else {
                // When the left bracket group event begins, an i-self statement is required
            	i++;
            }

        }
        
        if(!bool){
            // If the case'(('), i.e. left-loop group has not been resolved yet, it jumps out of the for loop (cool should be true if solved)
            return false;
        }else{
            return true;
        }
    }
    
}
Method 2: Origin: Stack:

Principle: Stack is FIFO, here we suggest drawing examples to aid understanding
What Stack can do is https://www.runoob.com/java/java-stack-class.html obtain
Traversing through a string, there are two ways to handle the current item:
(1) If the current item and the next item are not parentheses, and both items belong to left parentheses, then put the two items on the stack, subscript+2. If the two items are parentheses, subscript+2.
(2) If the current item belongs to the right parenthesis, that is,},],) then the value is taken from the stack, if the value and the item do not form a pair of parentheses, false is returned; if it belongs to the left parenthesis, repeat (1)

class Solution {
     public static boolean isValid(String s) {

        int len = s.length();
        if(len<=1){
            return false;
        }

        // Create a hash table
        Map<Character, Character> yes = new HashMap<Character, Character>();
        yes.put('{', '}');
        yes.put('[', ']');
        yes.put('(', ')');

        // Create Stack
        Stack <Character> left = new Stack<Character>();
        
        // Odd number term must be false 
        if (n % 2 == 1) {
            return false;
        }
	    // The first item is the right parenthesis
        if(s.charAt(i) != yes.get(left.pop())){
            return false;
        } else if (yes.containsKey(s.charAt(len-1))){
            // Last item is left parenthesis
            return false;
        }
        
        // Write as i<len-1: As appropriate[[[Errors will be reported]
        // After entering if (i+1<len&yes.containsKey(s.charAt(i+1))
        // i+2=0+2=2, because i+1<len&causes any if s to go in the next cycle I never increases the infinite loop by itself
        // Problem: In the case of'{[]}', the subscript cannot reach the position of the} (that is, the last item), causing the left to fail to empty the judgement of true to false
        // Solution: Outside the for loop, determine if the last item of the string will form a team with the one in the stack
        for(int i = 0; i < len - 1;){
            // The current item is a right parenthesis
            if(!yes.containsKey(s.charAt(i))){
                if(left.empty()){
                    return false;
                }
                if(s.charAt(i) != yes.get(left.pop())){
                    return false;
                }
                i++;
                continue;
            }
            // Current item is left parenthesis
            // I+1<len &&for overflow prevention, if overflow occurs, execution of s.charAt(i+1) will fail
            if(i+1<len && yes.get(s.charAt(i)) == s.charAt(i+1)){
                // The current item and the next item form a pair of parentheses
                i+=2;
            }else if(i+1<len && yes.containsKey(s.charAt(i+1))){
                // The current item and the next item are both left parentheses
                left.push(s.charAt(i));
                left.push(s.charAt(i+1));
                i+=2;
            }else if(i+1<len && !yes.containsKey(s.charAt(i+1))){
                // Next item is right parenthesis
                return false;
            }
        }
        // Solve the problem that subscript i cannot reach the last item of the string:
        // If left.pop() is called in an empty case, an error will be generated.
        // Execute & right part after success to determine if brackets are formed
        if(!left.empty() && s.charAt(len-1) == yes.get(left.peek())){
            // Existence such as'{}{}{}{}{} {(([]])]]', if pop method is used directly in the if judgment above
            // left will be cleared even though {and] do not match
            // This will make if(left.empty()) judgments outside of this nested if lose its effect
            // So let's use peek above and pop again if we get through here
            left.pop();
            
            // There are situations such as'([])'. If you just go through the above if judgment and return to true, you will judge false as true.
            // So add if judgment here
            if(left.empty()){
            	return true;   
            }
        }
       
        if(left.empty()){
            // As in case'[[[[]
            return true;   
        }
        return false;   
    }
    
}
Method 3: Stack given by official questions:
class Solution {
    public boolean isValid(String s) {
        int n = s.length();
        // Odd number must be false
        if (n % 2 == 1) {
            return false;
        }
		
        Map<Character, Character> pairs = new HashMap<Character, Character>() {{
            put(')', '(');
            put(']', '[');
            put('}', '{');
        }};
        Deque<Character> stack = new LinkedList<Character>();
        for (int i = 0; i < n; i++) {
            char ch = s.charAt(i);
            // If right parenthesis
            if (pairs.containsKey(ch)) {
                // The stack is not empty (no left parenthesis group) or (the top element of the stack does not match the current right parenthesis)
                if (stack.isEmpty() || stack.peek() != pairs.get(ch)) {
                    return false;
                }
                // if not, the pairing is successful and the top element is removed
                stack.pop();
            } else {
                // Store the current item on the stack as long as it is not a right parenthesis
                stack.push(ch);
            }
        }
        
        return stack.isEmpty();
    }
}
This method takes the right corresponding left in the hash table and encounters a left parenthesis and stores it on the stack, so it is two simplifications relative to my method

118. The difficulty is simple:

Method 1: Origin: Violent solution:

Understanding: Without looking at the given triangle dynamic diagram, looking at the returned array angle, you can get the following rules:
The first item of the array (which is also the first row of Yang Hui triangle) must be [1]. Then when the second row is generated, we add two extra values of 0 to the left and right of the first row to get [0,1,0],
At this point, the first + second = 0 + 1 = 1 of the array is the first element of the second row, the second + the third is the second element, and the third is the last element of the [0,1,0] array, so we have finished arranging the second row, that is, [1,1]
Generating the third line is the same, adding 0 to get [0,1,1,0], then repeating when two add up to one element until all elements are used up.
We can also see that the number of elements in each row equals the number of rows in that row.

So all we have to do is generate an array of rows based on the number of rows passed by the title, and add it to the result array every time an array of rows is generated.

Code implementation: There is an error here and there is a correction in the Code Interpretation section below
class Solution {
    public static List<List<Integer>> generate(int numRows) {
        List<List<Integer>> nums = new ArrayList<List<Integer>>();
        List<Integer> pre = new ArrayList<Integer>();
        
        int in = 0;
        pre.add(1);
        nums.add(pre);
        
        for(int i = 1; i<numRows; i++){
        	List<Integer> now = new ArrayList<Integer>();
            for(int j = 0; j<=i;j++){
                if(j == 0 || j == i){
                    in = pre.get(0); 
                }else{
                    in = pre.get(j-1) + pre.get(j); 
                }
                now.add(in);
            }
            nums.add(now);
            pre.add(0);
            Collections.copy(pre, now);
        }
        return nums;
    }
}
Code section explanation:

This involves the problem that elements in an array are arrays of different lengths: ordinary arrays and two-dimensional arrays cannot meet the requirements, so we use generics to set the element type of an array to an array.

List<List<Integer>> nums = new ArrayList<List<Integer>>();

Also note that the title requires us to return a List <List>, which is the array type List <List> that we set above, which means that the element array must be of List type. After this is set, we will end up with the same output format as in the title example.

List<Integer> pre = new ArrayList<Integer>();

There is a problem with this version of code, assuming that the final output of Input 3 is [[1, 2, 1], [1, 1], [1, 2, 1]:
Although I will write the creation of the array now as an element in the for loop, this will prevent each element array of nums from having the same address causing the values to be identical (if you write now on the first line in the first level for loop, you cannot write now.clean() at the end of the second level for loop to empty the values in now, otherwise all elements in nums assigned by now become empty)
But I copied the first element of nums using the array pre copy, which I did in the for loop Collections.copy(pre, now);The operation changed the value to the value of the second row of Yang Hui triangle.

// Solution: Add another one at the beginning as the value of the first element
List<List<Integer>> nums = new ArrayList<List<Integer>>();
        List<Integer> one = new ArrayList<Integer>();
        List<Integer> pre = new ArrayList<Integer>();
        
        int in = 0;
        one.add(1);
        pre.add(1);
        nums.add(one);

Part of the for loop:
First, the first line of the triangle has been written to death by me, so we start with the second line, so the first for loop starts with int i=1;(0 is the first line added, and starting with 0 makes it easy to get values from the array)
Considering the array subscript overflow problem, the second level for loop is designed to add an element to the current row based on the element of the previous row. The number of elements in the previous row is represented by the I of the first level for loop, so the number of elements in the current row is i+1. Writing as above in the current behavior of three lines (that is, when there are three elements in the current line) must loop three times.
If the judgement statement is to add the current value directly if the current item is the first or last value of the current line (because the first and last values are the same, get(0) is the correct value for both cases). else is the normal addition of two
When the second level for loop ends, the now array has all the values of the current row and can be added to the nums. At the same time, the now value is cloned to the PREAS the pre vious row.
Why write pre.add(0);This line of code: Because the number of pres is one less than now, this results in an error when running the copy method because the number of elements is different.
So add any number to the pre p.

Method 2: Mathematics: Time Complexity O(numRows2) Spatial Complexity O(1):

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> ret = new ArrayList<List<Integer>>();
        for (int i = 0; i < numRows; ++i) {
            List<Integer> row = new ArrayList<Integer>();
            for (int j = 0; j <= i; ++j) {
                if (j == 0 || j == i) {
                    row.add(1);
                } else {
                    // Using the returned result as an array to call the previous row of data directly avoids the creation and derivation of multiple arrays in Method 1
                    row.add(ret.get(i - 1).get(j - 1) + ret.get(i - 1).get(j));
                }
            }
            ret.add(row);
        }
        return ret;
    }
}

The basic principles and methods are consistent, and as a result my code is messy and long:

Despair

Tags: Java leetcode string Math stack

Posted on Tue, 12 Oct 2021 15:49:40 -0400 by vronsky