leetcode 14 day question brushing plan - efficient interview preparation

summary

The adjacency matrix is constructed from the given matrix

List<List<Integer>> graph = new ArrayList<>(n);
        for (int i = 0; i < n; ++i) graph.add(new ArrayList<>(3));
        for (int[] path : paths) {
            graph.get(path[0] - 1).add(path[1] - 1);
            graph.get(path[1] - 1).add(path[0] - 1);
        }

In a matrix that can go in four directions, it is usually wrong to use memo [] [because memo [] [] can only represent the results obtained by going in three directions at the current point, and it cannot go back. Therefore, for example, in question 79, in word search, we can judge in advance whether it is possible to search the target string, which is also a kind of pruning.

2021.08.11 day 1 summation problem

Sum of two numbers

Given an integer array nums and an integer target value target, please find the two integers with and as the target value target in the array and return their array subscripts.

Idea: traverse the array, put the traversed elements into the map, and then compare there to see if there is target num [i] in the map

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer>map=new HashMap();
        for(int i=0;i<nums.length;i++){
            if(map.containsKey(target-nums[i]))
               return new int[]{i,map.get(target-nums[i])};
            map.put(nums[i],i);
        }
        return null;
    }
}

2 167. Sum of two numbers II - input ordered array

class Solution {
    public int[] twoSum(int[] numbers, int target) {
       int i=0;int j=numbers.length-1;
       while(i<j){
           if(numbers[i]+numbers[j]<target) i++;
           else if(numbers[i]+numbers[j]>target) j--;
           else return new int[]{i+1,j+1};
       }
       return null;
    }
}

2021.08.12 day 2 summation problem

3.15 sum of three

Give you an array nums containing n integers. Judge whether there are three elements a, b and c in nums, so that a + b + c = 0? Please find all triples with a sum of 0 and no repetition.

Note: the answer cannot contain duplicate triples.

Solution ideas: fix the first number, and then use the double pointer to find the remaining two numbers. Remember to de duplicate each time. In order to avoid repetition, sort the array first to reduce the weight

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {  
        Arrays.sort(nums);
        List<List<Integer>>list=new ArrayList();
        for(int i=0;i<nums.length;i++){
            if(i>0&&nums[i]==nums[i-1])
              continue;//duplicate removal
            int L=i+1;int R=nums.length-1;
            while(L<R){
                 if(nums[L]+nums[R]>0-nums[i])
                   R--;
                 else if(nums[L]+nums[R]<0-nums[i])
                   L++;
                  else {
                    list.add(Arrays.asList(nums[i],nums[L],nums[R]));
                    int temp=nums[L];
                    int temp2=nums[R];
                    while(L<R&&nums[++L]==temp);//L remove the weight and pay attention to avoid crossing the boundary
                    while(L<R&&nums[--R]==temp2);//R remove the weight and pay attention to avoid crossing the boundary
                }                 
            }            
        }
     return list;
    }   
}

4.18 sum of four numbers

First look at the violence solution, quadruple for loop enumeration, then sort by using Collections.sort(ans), and then reduce the weight

class Solution {
      public static List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> resp = new ArrayList<>();
        for(int i=0;i<nums.length;i++){
            for(int j=i+1;j<nums.length;j++){
                for(int k=j+1;k<nums.length;k++){
                    for(int l=k+1;l<nums.length;l++){
                        if(nums[i]+nums[j]+nums[k]+nums[l] == target){
                            List<Integer> ans = new ArrayList<>();
                            ans.add(nums[i]);
                            ans.add(nums[j]);
                            ans.add(nums[k]);
                            ans.add(nums[l]);
                            Collections.sort(ans);
                            if(!resp.contains(ans)){
                               resp.add(ans); 
                            }
                        }
                    }
                }
            }
        }
        return resp;
    }
}

Then add a for loop to the sum of three numbers

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>>list=new ArrayList();
      for(int k=0;k<nums.length;k++){
        if(k>0&&nums[k]==nums[k-1])
              continue;//duplicate removal            
        for(int i=k+1;i<nums.length;i++){
            if(i>k+1&&nums[i]==nums[i-1])
              continue;//duplicate removal
            int L=i+1;int R=nums.length-1;
            while(L<R){
                 if(nums[L]+nums[R]>target-nums[k]-nums[i])
                   R--;
                 else if(nums[L]+nums[R]<target-nums[k]-nums[i])
                   L++;
                  else {
                    list.add(Arrays.asList(nums[k],nums[i],nums[L],nums[R]));
                    int temp=nums[L];
                    int temp2=nums[R];
                    while(L<R&&nums[++L]==temp);//L remove the weight and pay attention to avoid crossing the boundary
                    while(L<R&&nums[--R]==temp2);//R remove the weight and pay attention to avoid crossing the boundary
                }                 
            }            
        }
      }
      return list;
    }
}

The effect of pruning is still immediate

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        if (nums == null || nums.length < 4) {
            return result;
        }
        Arrays.sort(nums);
        int length = nums.length;
        // ergodic
        for (int i = 0; i < nums.length - 3; i++) {
            // prune
            if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
            if (nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target) continue;
            // duplicate removal
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            // Cycle the second number
            for (int j = i + 1; j < nums.length - 2; j++) {
                // prune
                if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
                if (nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target) continue;
                // duplicate removal
                if (j > i + 1 && nums[j] == nums[j - 1]) continue;
                // Define pointer
                int left = j + 1, right = nums.length - 1;
                while (left < right) {
                    int sum = nums[i] + nums[j] + nums[left] + nums[right];
                    if (sum > target) {
                        right--;
                    } else if (sum < target) {
                        left++;
                    } else if (sum == target) {
                        result.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
                        // De duplication after finding an array
                        while (left < right && nums[right] == nums[right - 1]) right--;
                        while (left < right && nums[left] == nums[left + 1]) left++;
                        // Move pointer
                        right--;
                        left++;
                    }
                }                
            }
        }
        return result;
    }
}

2021.08.13 fiboracci series on the third day

5 509. Fibonacci number

class Solution {
    public int fib(int n) {
      if(n<=1)
        return n;
      int a=0,b=1,c=0;
      for(int i=1;i<n;i++){
           c=a+b;
           a=b;
           b=c;
      }
     return c;
    }
}

6.70. Climbing stairs

Suppose you are climbing stairs. You need n steps to reach the roof.

You can climb one or two steps at a time. How many different ways can you climb to the roof?

Note: given n is a positive integer.

The idea of solving the problem is that the nth stairs can be obtained by jumping one step of the Nth-1 stairs or two steps of the nth-2 stairs. Therefore, f(n) = f(n-1+f(n-2)

class Solution {  
    public int climbStairs(int n) {
      if(n<3)
        return n;
      int a=1,b=2,c=0;
       for(int i=3;i<=n;i++){
          c=a+b;
          a=b;
          b=c;
       }
       return c;
    }   
}

2021.08.14 day 4 dynamic programming method

7 53. Maximum subsequence sum

Given an integer array nums, find a continuous sub array with the largest sum (the sub array contains at least one element) and return its maximum sum.

Idea: dp[i] represents the maximum suborder sum at the end of each element,

If the maximum suborder sum at the end of the previous element is greater than 0, the maximum suborder sum at the end of the current element is the sum of the current element plus the maximum suborder sum at the end of the previous element

Otherwise, the maximum sub order sum at the end of the current element is the current element

class Solution {
    public int maxSubArray(int[] nums) {
        int dp[]=new int [nums.length];
        dp[0]=nums[0];
        int max=dp[0];
        for(int i=1;i<nums.length;i++){           
            dp[i]=dp[i-1]>0?nums[i]+dp[i-1]:nums[i];             
            max=Math.max(dp[i],max);
        }
        return max;      
    }     
}
class Solution {
    public int maxSubArray(int[] nums) {
         //The solution idea is to discard the sequence before the current pointer if it is less than 0, that is, do not participate in the subsequent calculation if it is less than 0, and add it to num [i] if it is greater than 0
         
         int curSum=nums[0];              
         int max=nums[0];
         for(int i=1;i<nums.length;i++)
         {
            if(nums[i-1]>0)  nums[i]=nums[i-1]+nums[i];          
            max=Math.max(nums[i],max);
         }        
     return max;
    }
}

class Solution {
    public int maxSubArray(int[] nums) {
      int result=Integer.MIN_VALUE;
      int sum=0;
      for(int i=0;i<nums.length;i++)
      {
          sum+=nums[i];
          if(sum>result) result=sum;
          if(sum<0) sum=0;
      }
    return result;
    }
}

8 416. Segmentation and subsets

Give you a non empty array num containing only positive integers. Please judge whether you can divide this array into two subsets so that the sum of the elements of the two subsets is equal.

Train of thought 1 memorization and regression search,
The last one

 return memo[i][target] = dfs(nums, target - nums[i], i + 1, memo) || dfs(nums, target, i + 1, memo);

It means that num [i] can be taken or not taken. If it is not taken, it is necessary to search for target in the next element. If it is taken, it is necessary to search for target - num [i] in the next element.

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = Arrays.stream(nums).sum();
        if (sum % 2 != 0) return false;
        Arrays.sort(nums);
        return dfs(nums, sum / 2, 0, new Boolean[nums.length][sum / 2 + 1]);
    }

    private boolean dfs(int[] nums, int target, int i, Boolean[][] memo) {
        if (i >= nums.length || nums[i] > target) 
            return false;
        if (nums[i] == target) 
            return true;
        if (memo[i][target] != null)
            return memo[i][target];
        return memo[i][target] = dfs(nums, target - nums[i], i + 1, memo) || dfs(nums, target, i + 1, memo);
    }
}

Idea 2: dynamic programming

Considering the current element, dp will be transferred from a number on the left of the previous line. For example, the current num [i] is equal to 5 and target=9. When we go to 5, we need to consider whether the previous num elements can be rounded up to 4

Regardless of the current element, the state is directly copied from the previous grid. What can be composed originally and what can be composed now

class Solution {
    public boolean canPartition(int[] nums) {
        //In essence, it is a 0,1 knapsack problem to find whether the sum of several numbers in the array can reach half of the sum of all elements of the array, and each element can only be used once
        int sum=0;
        int max=0;
        for(int i=0;i<nums.length;i++){
           sum+=nums[i];
           max=Math.max(nums[i],max);
        }          
        if(sum%2!=0||max>sum/2) 
            return false;
         int target=sum/2; 
        boolean dp[][]=new boolean[nums.length+1][target+1];
        
        for(int i=1;i<=nums.length;i++) {
            for(int j=0;j<=target;j++){
                if(nums[i-1]>j)//You can't use nums[i-1] to form j, you can only use the result of the previous line
                    dp[i][j]=dp[i-1][j];//Copy the result of the previous line directly                
                else if(nums[i-1]<j)//You can use the current num [I-1] to form J. it also depends on whether the previous elements can form j-num [I-1], or you can directly copy the previous results without the current num [I-1], and the two are the same
                    dp[i][j]=dp[i-1][j]||dp[i-1][j-nums[i-1]];                 
                else
                 dp[i][j]=true;//j can be formed because nums[i-1]=j
            }
        }
        return dp[nums.length][target];
    }
}

???

9 322. Change

public class Solution {
    public int coinChange(int[] coins, int amount) {
        int max = amount + 1;
        int[] dp = new int[amount + 1];
        Arrays.fill(dp, max);
        dp[0] = 0;
        for (int i = 1; i <= amount; i++) {
            for (int j = 0; j < coins.length; j++) {
                if (coins[j] <= i) {
                    dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                }
            }
        }
        return dp[amount] > amount ? -1 : dp[amount];
    }
}

I used hashSet to write timeout before

public class Solution {
    public int coinChange(int[] coins, int amount) {
        if(amount==0) return 0;
        int dp[]=new int [amount+1];
        dp[0]=0;
        Set<Integer>set=new HashSet();
        for(int i=0;i<coins.length;i++) set.add(coins[i]);
        for(int i=1;i<=amount;i++)
        {   
            dp[i]=Integer.MAX_VALUE;
            if(set.contains(i))   dp[i]=1;          
            else {
                  for(int j=1;j<=i/2;j++)
                 {
                     if(dp[j]!=-1&&dp[i-j]!=-1)                                  
                        dp[i]=Math.min(dp[i],dp[j]+dp[i-j]);
                 }
                if(dp[i]==Integer.MAX_VALUE) dp[i]=-1;
            }                           
        }
     return  dp[amount];
    } 
}

2021.08.15 day 5 stack

10 20. Valid brackets

Given a string s that only includes' (',') ',' {','} ',' [','] ', judge whether the string is valid.

Valid strings must meet:

The left parenthesis must be closed with the same type of right parenthesis.
The left parentheses must be closed in the correct order.
class Solution {
    public boolean isValid(String s) {
         Stack<Character>stack=new Stack();            
            for(int i=0;i<s.length();i++){
             if(s.charAt(i)==')'){
                 if(!stack.isEmpty()&&stack.peek()=='(') stack.pop();
                 else  return false;
             }
             else if(s.charAt(i)=='}'){
                 if(!stack.isEmpty()&&stack.peek()=='{') stack.pop();
                 else  return false;
             }
             else if(s.charAt(i)==']'){
                 if(!stack.isEmpty()&&stack.peek()=='[') stack.pop();
                 else  return false;
             }
             else
               stack.push(s.charAt(i));
         }        
       return stack.isEmpty();    
    }
}

11 496. Next larger element I

Give you two arrays nums1 and nums2 without duplicate elements, where nums1 is a subset of nums2.

Please find out the next larger value of each element in nums1 in nums2.

The next larger element of the number x in nums1 refers to the first element larger than x to the right of the corresponding position in nums2. If it does not exist, the corresponding position outputs - 1.

Idea 1: where is the violence ratio? Now find the corresponding element in array 1 in array 2, and then find the next element larger than the element from this position

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int arr[]=new int [nums1.length];      
        for(int i=0;i<nums1.length;i++){            
              int j=0;
                while(j<nums2.length&&nums2[j]!=nums1[i])
                     j++;
                j++;//Move back one bit     
                while(j<nums2.length&&nums2[j]<nums1[i])
                     j++;
                 arr[i]=j>=nums2.length?-1:nums2[j];
                      
        }
        return arr;
    }
}

I'm also stupid. I can modify the original array nums1 without additional space

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        for(int i=0;i<nums1.length;i++){            
                int j=0;
                while(j<nums2.length&&nums2[j++]!=nums1[i]);                                 
              
                while(j<nums2.length&&nums2[j]<nums1[i])
                    j++;                                               
                 nums1[i]=j>=nums2.length?-1:nums2[j];
        }
        return  nums1;
    }
}

In fact, finding the first number on the right that is greater than yourself is a typical "stack" application (also known as "monotone stack"), which puts each element into and out of the stack once. In this process, you can find the first number on the right that is greater than yourself.

Idea 2: monotone stack

After traversing nums2, if no smaller element is found from front to back, put the element on the stack, and then find one larger than the top of the stack, store the top of the stack element and the corresponding larger element in the map, pop up the top of the stack, and pay attention to the cyclic comparison of the top of the stack

Finally, for elements that cannot be found in the map, the corresponding value is set to - 1;

public class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;

        Stack<Integer> stack = new Stack<>();
        Map<Integer, Integer> map = new HashMap<>();
        // First process nums2 and store the corresponding relationship in the hash table
        for (int i = 0; i < len2; i++) {
            while (!stack.isEmpty() && stack.peek() < nums2[i]) {
                map.put(stack.pop(), nums2[i]);
            }
            stack.add(nums2[i]);
        }
        // Traverse nums1 to get the result set    
        for (int i = 0; i < len1; i++) {
            nums1[i] = map.getOrDefault(nums1[i], -1);
        }
        return nums1;
    }
}

503. Next larger element II

Given a circular array (the next element of the last element is the first element of the array) , output the next larger element of each element. The next larger element of the number x is in the order of array traversal, and the first larger number after this number means that you should search for its next larger number cyclically. If it does not exist, output - 1.

Problem solving ideas, straighten the circular array

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int n=nums.length;
        int ret[]=new int[n];
        Arrays.fill(ret, -1);
        Stack<Integer>stack=new Stack();      
       // Map<Integer,Integer>map=new HashMap();// There are duplicate elements in the array, so it's not easy to use map
        for(int i=0;i<n*2-1;i++){
            while(!stack.isEmpty()&&nums[stack.peek()]<nums[i%n]){
                    ret[stack.pop()]=nums[i%n];  
            }           
                   //stack.push(nums[i%n]);
                   stack.push(i%n);//Save the index, absolutely
        }     
        return ret;
    }
}

Improved version, otherwise there will be repeated judgment

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int n=nums.length;
        int ret[]=new int[n];
        Arrays.fill(ret, -1);
        Stack<Integer>stack=new Stack();      
        for(int i=0;i<n*2-1;i++){
            while(!stack.isEmpty()&&nums[stack.peek()]<nums[i%n]){
                    ret[stack.pop()]=nums[i%n];  
            }                           
            if(ret[i%n]==-1)
               stack.push(i%n);//Save the index, absolutely
        }     
        return ret;
    }
}

Static array

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int n = nums.length;
        int[] ans = new int[n];
        Arrays.fill(ans, -1);
        // Use the array to simulate the stack. hh represents the bottom of the stack and tt represents the top of the stack
        int[] d = new int[n * 2];
        int hh = 0, tt = -1;
        for (int i = 0; i < n * 2; i++) {
            while (hh <= tt && nums[i % n] > nums[d[tt]]) {
                int u = d[tt--];
                ans[u] = nums[i % n];
            }
            d[++tt] = i % n;
        }
        return ans;
    }
}

12 456.132 mode

Give you an integer array nums. There are n integers in the array. The subsequence of 132 mode is composed of three integers nums[i], nums[j] and nums[k], and satisfies I < J < K and nums[i] < nums[k] < nums[j].

If there is a subsequence of 132 mode in nums, return true; Otherwise, false is returned.

reference resources: Graphical monotone stack

class Solution {
        public boolean find132pattern(int[] nums) {
        int len=nums.length;
        if(len<3) return false;
        Stack<Integer> st=new Stack<>();
        int K=-1;
        for(int I=len-1;I>=0;I--){
            if(K>-1&&nums[K]>nums[I]) return true;
            while(!st.isEmpty()&&nums[st.peek()]<nums[I]){
                K=st.pop();
            }
            st.push(I);
        }
        return false;
    }

}

2021.08.16 day 6 figures

13 119. Yanghui triangle II

class Solution {
    public List<Integer> getRow(int rowIndex) {
     List<List<Integer>>list=new ArrayList();
     for(int i=0;i<=rowIndex;i++){
         List list2=new ArrayList();       
         for(int j=0;j<=i;j++){  
             if(j==0||j==i){
                 list2.add(1);
             }else{
                 list2.add(list.get(i-1).get(j-1)+list.get(i-1).get(j));
             }
         }
         list.add(list2);
     }
     return list.get(rowIndex);
    }
}
class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<Integer> pre = new ArrayList<Integer>();
        for (int i = 0; i <= rowIndex; ++i) {
            List<Integer> cur = new ArrayList<Integer>();
            for (int j = 0; j <= i; ++j) {
                if (j == 0 || j == i) {
                    cur.add(1);
                } else {
                    cur.add(pre.get(j - 1) + pre.get(j));
                }
            }
            pre = cur;
        }
        return pre;
    }
}

14 279. Complete square

Solution idea: first judge whether the current I is a complete square number. If so, dp[i]=1; If not, traverse the previous dp in turn to find the smallest one in dp[j]+dp[i-j], that is, the least square number of components j plus the least square number of components i-j, and add it to 1 / 2, because it will be repeated later

class Solution {
    public int numSquares(int n) {
       int dp[]=new int[n+1];
       for(int i=1;i<=n;i++){
           if((int)Math.sqrt(i)*(int)Math.sqrt(i)==i){
               dp[i]=1;
           }
           else{
               dp[i]=Integer.MAX_VALUE;
               for(int j=1;j<=i/2;j++){
                   dp[i]=Math.min(dp[j]+dp[i-j],dp[i]);
               }
           }
       }
       return dp[n];
    }
}

Problem solving ideas 2

class Solution {
    public int numSquares(int n) {
        int[] f = new int[n + 1];
        for (int i = 1; i <= n; i++) {
            int minn = Integer.MAX_VALUE;
            for (int j = 1; j * j <= i; j++) {
                minn = Math.min(minn, f[i - j * j]);
            }
            f[i] = minn + 1;
        }
        return f[n];
    }
}

Problem solving thinking 3 BFS

The value of each node is the accumulation from the root node to the current node. The number of squares is actually the cumulative sum equal to target when traversing to which layer. We only need to traverse layer by layer, that is, BFS. When the cumulative sum is equal to target, we can directly return the current number of layers.

Reference: [data structure and algorithm] BFS, dynamic programming, Lagrange's square sum theorem, etc

class Solution{
public int numSquares(int n) {
    Queue<Integer> queue = new LinkedList<>();
    //Record the accessed node values
    Set<Integer> visited = new HashSet<>();
    queue.offer(0);
    visited.add(0);
    //Which layer of the tree
    int level = 0;
    while (!queue.isEmpty()) {
        //Number of nodes per layer
        int size = queue.size();
        level++;
        //Traverse all nodes of the current layer
        for (int i = 0; i < size; i++) {
            //The value of the node
            int digit = queue.poll();
            //Accessing the child nodes of the current node is similar to the left and right child nodes of a binary tree
            for (int j = 1; j <= n; j++) {
                //Values of child nodes
                int nodeValue = digit + j * j;
                //nodeValue is always the sum of perfect squares when it is equal to n
                //When to return directly
                if (nodeValue == n)
                    return level;
                //If greater than n, terminate the inner loop
                if (nodeValue > n)
                    break;
                if (!visited.contains(nodeValue)) {
                    queue.offer(nodeValue);
                    visited.add(nodeValue);
                }
            }
        }
    }
    return level;
}
}

15 483. Minimum good base

August 17, 2021 day 7 tree

16 112. Path sum

class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
       if(root==null)
        return false;
       if(root.left==null&&root.right==null)
        return root.val==sum;        
       return hasPathSum(root.right, sum-root.val)|| hasPathSum(root.left, sum-root.val);                
    }
}

Idea 2: sequence traversal: one queue stores the node, and the other queue stores the sum value when adding the current node val

17 230. The K-th smallest element in the binary search tree

Since it is a binary search tree, then the middle order traversal is an ordered ascending sequence. Let's just go through the middle order traversal directly. 2

class Solution {
    int count=0;
    int val=-1;
    public int kthSmallest(TreeNode root, int k) {
        inOrder(root,k);
        return val;
    }
    public void inOrder(TreeNode root, int k){
        if(root==null)
          return ;
         inOrder(root.left, k);
         count++;
         if(count==k){
             val= root.val;
             return;
         }
        inOrder(root.right, k);       
    }    
}

Train of thought 2;: Order traversal in iteration

18 968. Monitoring binary tree

Reference for problem solving ideas: 968. Monitoring binary tree: [state transition on recursion] detailed explanation

class Solution {
    int res=0;
    public int minCameraCover(TreeNode root) {       
       return  dfs(root)==0?res+1:res;//If the parent node is in an uncovered state, you need to add a camera to the parent node
    }
    public int dfs(TreeNode root){
        if(root==null)
           return 2;//Node has coverage
        int left=dfs(root.left);
        int right=dfs(root.right);
        //0 means no coverage, 1 means there is a camera, 2 means there is coverage, and the left and right nodes can form 9 states
        //(00,01,02,10,11,12,20,21,22)
               
        //As long as there is no coverage, the parent node needs a camera to cover the child node 00,01,10,20,02
        if(left==0||right==0){
            res++;
            return 1;
        }
         //As long as one of the child nodes has a camera, the parent node will be covered 11,21,12
        if(left==1||right==1){
            return 2;
        }
        //Another is 22. The two child nodes are covered. The parent node can have no camera and can use its own parent node
        return 0;
    }
}

2021.08.18 day 8 string

(19) 720. The longest word in the dictionary

Problem solving ideas

20 3. Longest substring without repeated characters

Given a string s, please find the length of the longest substring that does not contain duplicate characters.

Problem solving idea: traverse the character array. If there is no such character in the map, directly put the character into the container, and define a left pointer and a max
If the current character already exists in the container, record a current max value max=Math.max(i-left,max);
At this time, the left pointer should also judge whether it needs to move to the next repeated character. For abba, b repeats first, and left points to 2. Now a repeats, and left cannot point to 1, but continues to point to 2. Therefore, left = math.max (left, map.get (arr [I]) + 1; That is, the left pointer cannot move back
Finally, it is also necessary to judge whether the last character is a non repeated number. max=Math.max(arr.length-left,max);

class Solution {
    public int lengthOfLongestSubstring(String s) {
      if(s.length()<=1)
         return s.length();
      int left=0;int max=0;     
      Map<Character,Integer>map=new HashMap();
      char arr[]=s.toCharArray();
      for(int i=0;i<arr.length;i++){
          if(!map.containsKey(arr[i])){
              map.put(arr[i],i);
          }
          else{
              max=Math.max(i-left,max);
              left=Math.max(left,map.get(arr[i])+1);
              map.put(arr[i],i);              
          }        
      }
       max=Math.max(arr.length-left,max); 
      return max;
    }
}

Modify the code of the second edition as follows

class Solution {
    public int lengthOfLongestSubstring(String s) {    
      int left=0;int max=0;     
      Map<Character,Integer>map=new HashMap();
      char arr[]=s.toCharArray();
      for(int i=0;i<arr.length;i++){
          if(map.containsKey(arr[i])){                      
            max=Math.max(i-left,max);
            left=Math.max(left,map.get(arr[i])+1);                         
          }  
           map.put(arr[i],i);        
      }
      max=Math.max(arr.length-left,max); 
      return max;
    }
}

Problem solving idea 2, map each character to the array
Check whether the number of characters in the sliding window is greater than 1. If it is greater than 1, make a max judgment, and move the left pointer until the number of characters is greater than 1

class Solution {
    public int lengthOfLongestSubstring(String s) {
     int arr[]=new int[128];
     char arr1[]=s.toCharArray();
     int left=0;int max=0;
     for(int i=0;i<arr1.length;i++){
         arr[arr1[i]-32]++;
         if(arr[arr1[i]-32]>1){
             max=Math.max(max,i-left);
             while(arr[arr1[i]-32]>1){
              arr[arr1[left]-32]--;
              left++;
         }
        }       
     }
    return  max=Math.max(max,s.length()-left);
    }
}

21 97. Interleaved string

Solution idea: dynamic programming, see if the first j characters of s1 and s2 can form the first i+j characters of s3

reference resources: Dynamic programming explains Python 3 line by line

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
      int m=s1.length();
      int n=s2.length();
      int p=s3.length();
       if(m+n!=p)
         return false;
       boolean dp[][]=new boolean[m+1][n+1];    
      //dp[i][j] indicates whether the I characters of s1 and the first j characters of s2 can form the first i+j characters of s3     
         dp[0][0]=true;
        for(int i=1;i<=m;i++)//Fill in the first column
            dp[i][0]=dp[i-1][0]&&s1.charAt(i-1)==s3.charAt(i-1);
        for(int j=1;j<=n;j++)//Fill in the first line
            dp[0][j]=dp[0][j-1]&&s2.charAt(j-1)==s3.charAt(j-1);    
        for(int i=1;i<=m;i++){
          for(int j=1;j<=n;j++){
            //dp[i][j] can be changed from dp[i-1][j] and dp[i][j-1]                   
            dp[i][j]=(dp[i-1][j]&&s1.charAt(i-1)==s3.charAt(i+j-1))||
            (dp[i][j-1]&&s2.charAt(j-1)==s3.charAt(i+j-1));
          }
      }
      return dp[m][n];
    }
}

Problem solving idea 2, depth first traversal, search each character of s3 in s1 and s2, which is essentially a path search

reference resources:
https://leetcode-cn.com/problems/interleaving-string/solution/lei-si-lu-jing-wen-ti-zhao-zhun-zhuang-tai-fang-ch/

class Solution {
    private boolean[][] visited;
    
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1.length() + s2.length() != s3.length())
            return false;
        visited = new boolean[s1.length() + 1][s2.length() + 1];
        return backtrack(s1, s2, s3, 0, 0, 0);
    }

    private boolean backtrack(String s1, String s2, String s3, int i, int j, int k) {
        if (k == s3.length())//All characters of description s3 are matched
            return true;
        if (visited[i][j])//If the current node has been accessed, it means that the previous path cannot go through it. Even if you go through the same node in another way, it still cannot go through
            return false;//In the two-dimensional matrix, this element has been accessed, which means that its right and lower sides have been accessed, but it doesn't work. If we go through this point another way, it must still not work
        visited[i][j] = true;
        if (i < s1.length() && s1.charAt(i) == s3.charAt(k)
                && backtrack(s1, s2, s3, i + 1, j, k + 1)
            || j < s2.length() && s2.charAt(j) == s3.charAt(k)
                && backtrack(s1, s2, s3, i, j + 1, k + 1))
            return true;

        return false;
    }
}

August 19, 2021 day 9

(22) 28. Implement str ()

23 524. Match the longest word in the dictionary by deleting letters

Give you a string s and a string array dictionary as a dictionary, find and return the longest string in the dictionary, which can be obtained by deleting some characters in S.

If there is more than one answer, the string with the longest length and the smallest dictionary order is returned. If the answer does not exist, an empty string is returned.

Example 1:

Input: s = "abpcplea", dictionary = ["ale", "apple", "monkey", "plea"]
Output: "apple"

Example 2:

Input: s = "abpcplea", dictionary = ["a", "b", "c"]
Output: "a"

Problem solving ideas

public class Solution {
    public boolean isSubsequence(String x, String y) {
        int j = 0;
        for (int i = 0; i < y.length() && j < x.length(); i++)
            if (x.charAt(j) == y.charAt(i))
                j++;
        return j == x.length();
    }
    public String findLongestWord(String s, List < String > d) {
        String max_str = "";
        for (String str: d) {
            if (isSubsequence(str, s)) {
                if (str.length() > max_str.length() || (str.length() == max_str.length() && str.compareTo(max_str) < 0))
                    max_str = str;
            }
        }
        return max_str;
    }
}


(24) 1392. Longest prefix

2021.08.20 day 10

25 1042. Non contiguous flower planting

Problem solving idea: build an adjacency matrix, and then compare each node there to see what flowers are used in its adjacency nodes. It will just put another kind of flowers. Since there are up to 3 paths in each garden and 4 kinds of flowers, we can certainly find a matching answer.

reference resources: The idea is very simple and difficult to implement (coloring problem)

class Solution {
    public int[] gardenNoAdj(int n, int[][] paths) {
       Map<Integer,Set<Integer>>graph=new HashMap();
       for(int i=1;i<=n;i++)
         graph.put(i,new HashSet());
       for(int []path:paths){
            graph.get(path[0]).add(path[1]);
            graph.get(path[1]).add(path[0]);
       }
       int res[]=new int[n];
       for(int i=1;i<=n;i++){
           boolean[]used=new boolean[5];
           for(int adj:graph.get(i))
                used[res[adj-1]]=true;//Find the unused 1-4 parts of adjacent points// For example, adj=1,res[0]=0 description
                //Res was originally 0. If it is not 0, it means that a flower has been put into res
            for(int j=1;j<=4;j++){
                if(!used[j])
                   res[i-1]=j;
            }
       }
       return res;
    }
}

class Solution {
    public int[] gardenNoAdj(int n, int[][] paths) {
        List<List<Integer>> graph = new ArrayList<>(n);
        for (int i = 0; i < n; ++i) graph.add(new ArrayList<>(3));
        for (int[] path : paths) {
            graph.get(path[0] - 1).add(path[1] - 1);
            graph.get(path[1] - 1).add(path[0] - 1);
        }
        int[] ans = new int[n];
        for (int i = 0; i < n; ++i) {
            boolean[] used = new boolean[5];
            for (int j : graph.get(i)) used[ans[j]] = true;
            int t = 1;
            while (used[t]) ++t;
            ans[i] = t;
        }
        return ans;
    }
}

import java.util.Arrays;

public class Solution {
    public int[] gardenNoAdj(int n, int[][] paths) {
        int[] res = new int[n];
        if(paths.length == 0){
            Arrays.fill(res,1);
            return res;
        }
        int[][] adjoinGarden = new int[n + 1][3];
        int[] gardenSize = new int[n + 1];
        for (int[] p : paths) {
            int v1 = p[0];
            int v2 = p[1];
            adjoinGarden[v1][gardenSize[v1]++] = v2;
            adjoinGarden[v2][gardenSize[v2]++] = v1;
        }
        for (int i = 1; i <= n; i++) {
            boolean[] color = new boolean[4];
            for (int j : adjoinGarden[i]) {
                if (j != 0 && res[j - 1] != 0) {
                    color[res[j - 1] - 1] = true;
                }
            }
            if (!color[0]) {
                res[i - 1] = 1;
            } else if (!color[1]) {
                res[i - 1] = 2;
            } else if (!color[2]) {
                res[i - 1] = 3;
            } else {
                res[i - 1] = 4;
            }
        }
        return res;
    }
}

26 787. The cheapest flight in the transfer station K

Problem solving ideas, summarize and constantly change src in the process of backtracking, and record cost at the same time

Timeout. If I search memo [] [] by memory, I will still make an error, because memo [] [] can only represent the minimum value of memo when the last point passes here, not the minimum value from memo [] [] to dst

class Solution {
    List<List<Integer>>graph=new ArrayList();
    int[][]costs;
  //  Integer[][]memo;
    boolean visited[];
    int max;
    //
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
      costs=new int[n][n];
    //  memo=new Integer[n][n];
      visited=new boolean[n];
      max=n;    
      for(int i=0;i<n;i++)
        graph.add(new ArrayList());//Add n critical tables
      for(int[] flight:flights){         
          costs[flight[0]][flight[1]]=flight[2];//Initialization cost
         // costs[flight[1]][flight[0]]=flight[2];// Initialization cost / / note that it is a directed graph
          graph.get(flight[0]).add(flight[1]);//Initialize adjacency table
        //  graph.get(flight[1]).add(flight[0]);// Initialize adjacency table
      }   
       int result=dfs(src,dst,k+2,0);
       return (result ==max*10000) ?-1:result;
    }
    public int  dfs(int src,int dst,int k, int cost){         
           
           if((src==dst)&&k>0){
           //The destination has been reached. Record the current cost
           //    return memo[src][dst]=cost;
             return cost;
           }
           if(k<=0)//There are more than k transfer stations, which do not meet the requirements. A larger value is returned
              return max*10000;
         //   if(memo[src][dst]!=null)   
           //    return  memo[src][dst];                         
            if(visited[src])
              return max*10000 ; //Cannot reverse access              
            visited[src]=true;
           int result= max*10000 ;
           for(int i=0;i<graph.get(src).size();i++){                               
              if(costs[src][graph.get(src).get(i)]>0){//Note that it is a directed graph. If it is not greater than 0, it indicates that there is no connection before two points and cannot take off
                 int temp1= dfs(graph.get(src).get(i),dst,k-1,cost+costs[src][graph.get(src).get(i)]); 
                 result=Math.min(result,temp1);  
              }                                                                   
        }   
          visited[src]=false; 
          return result;   
         // return memo[src][dst]=result;                                 
    }
}

Although the official deep search also timed out, there are more examples that can pass because there are more pruning bars, and the minimum value of res is reflected here

public class Solution {

    private int[][] graph;
    private boolean[] visited;
    private int res = Integer.MAX_VALUE;

    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        K = Math.min(K, n - 2);

        this.graph = new int[n][n];
        for (int[] flight : flights) {
            graph[flight[0]][flight[1]] = flight[2];
        }

        this.visited = new boolean[n];
        // Start depth first traversal. Note: K + 1 is transmitted here because there are k stops, a total of K + 1 stations
        dfs(src, dst, K + 1, 0);

        if (res == Integer.MAX_VALUE) {
            return -1;
        }
        return res;
    }


    /**
     * Starting from src to dst, you can pass station k at most (here k includes src)
     *
     * @param src  starting station
     * @param dst  Terminus
     * @param k    Number of sites passed
     * @param cost Price spent
     */
    private void dfs(int src, int dst, int k, int cost) {
        if (src == dst) {
            res = cost;
            return;
        }

        if (k == 0) {
            return;
        }

        for (int i = 0; i < graph[src].length; i++) {
            if (graph[src][i] > 0) {
                if (visited[i]) {
                    continue;
                }

                // Pruning: skip paths that may incur higher costs to select the least price
                if (cost + graph[src][i] > res) {
                    continue;
                }

                visited[i] = true;
                dfs(i, dst, k - 1, cost + graph[src][i]);
                visited[i] = false;
            }
        }
    }
}


Author: LeetCode
 Link: https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/solution/k-zhan-zhong-zhuan-nei-zui-bian-yi-de-hang-ban-b-2/
Source: force buckle( LeetCode)
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

A brother's memory search

class Solution {
    // See DAG
    // dp[i][j][k], the minimum cost of the most transfer K stations from station I to station j! Look at the title description and naturally think of this state
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        int[][] cost = new int[n][n];
        for(int i = 0; i < flights.length; i++){
            int st = flights[i][0];
            int en = flights[i][1];
            int price = flights[i][2];
            cost[st][en] = price;
        }
        int[][][] dp = new int[n][n][K+2];
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                Arrays.fill(dp[i][j], -1);
            }
        }
        int res = f(cost, src, dst, K+1, dp);
        return res >= 1000000 ? -1 : res;
    }
    private int f(int[][] cost, int src, int dst, int K, int[][][] dp){
        if(K < 0){
            return 1000000;   
        }
        if(dp[src][dst][K] != -1){
            return dp[src][dst][K];
        }
        if(src == dst){
            return dp[src][dst][K] = 0;
        }
        int ans  = Integer.MAX_VALUE;
        for(int i = 0; i < cost.length; i++){
            if(cost[src][i] != 0){
                ans = Math.min(ans, cost[src][i] + f(cost, i, dst, K-1, dp));
            }
        }
        return dp[src][dst][K] = (ans == Integer.MAX_VALUE ? 1000000 : ans);
    }
}

dynamic programming

class Solution {
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        // dp[i][k] is the minimum cost of arriving at station I after passing through K transfer stations
        int[][] dp = new int[n][K + 1];

        // Loop initializes the entire two-dimensional array.
        for(int i = 0; i < n; ++i) Arrays.fill(dp[i], Integer.MAX_VALUE);

        // Use the information in flights to initialize the direct shift of src
        for(int[] flight : flights) {
            if(flight[0] == src){
                dp[flight[1]][0] = flight[2];
            }
        }

        // Loop initializes the row with dst == src in the array
        for(int i = 0; i <= K; i++){
            dp[src][i] = 0;
        }

        //Dynamic programming state transition equation, start filling in the form
        //The direct has been initialized (i.e. in the case of k = 0). Now it starts from k = 1, that is, there is only one transfer station
        for(int k = 1; k <= K; k++){
            for(int[] flight : flights){
                //Combined with topic understanding
                if(dp[flight[0]][k - 1] != Integer.MAX_VALUE){
                    dp[flight[1]][k] = Math.min(dp[flight[1]][k], dp[flight[0]][k - 1] + flight[2]);
                }
            }
        }
        return dp[dst][K] == Integer.MAX_VALUE? -1: dp[dst][K];
    }
}

Breadth first search, also timeout?
I also want to mark the searched nodes. It doesn't seem to work

class Solution {
      List<List<Integer>>graph=new ArrayList();
      int[][]costs;
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
        costs=new int[n][n];
        for(int i=0;i<n;i++)
            graph.add(new ArrayList());//Add n critical tables
        for(int[] flight:flights){         
            costs[flight[0]][flight[1]]=flight[2];//Initialization cost    
            graph.get(flight[0]).add(flight[1]);//Initialize adjacency table
        }
         boolean visited[]=new boolean[n];
         Queue<Integer>queue=new LinkedList();
         Queue<Integer>cost=new LinkedList();
         int result=Integer.MAX_VALUE;
         queue.offer(src);
         visited[src]=true;
         cost.offer(0);
         int count=0;
        while(!queue.isEmpty()){
            int size=queue.size();
            count++;
            if(count>k+2){
                break;
            }
            for(int j=0;j<size;j++){
            int temp=queue.poll();
            int tempCost=cost.poll();
            if(temp==dst){
                 result=Math.min(result,tempCost);
            }
            for(int i=0;i<graph.get(temp).size();i++){
                if(!visited[graph.get(temp).get(i)]){
                       queue.offer(graph.get(temp).get(i));
                       cost.offer(tempCost+costs[temp][graph.get(temp).get(i)]);
                }
                   
            }
          }
        } 
        return result==Integer.MAX_VALUE?-1:result;  
    }
}

After pruning, more examples can be passed

There is an 8ms, which can be passed

class Solution {
    public int findCheapestPrice(int n, int[][] flights, int src, int dst, int K) {
        // Used to record (current city, information list of cities that can fly to (each item includes [city coordinates, cost]))
        Map<Integer, List<int[]>> map = new HashMap<>();
        // Create map information
        for(int[] flight: flights) {
            List<int[]> list = map.getOrDefault(flight[0], new ArrayList<>());
            list.add(new int[]{flight[1], flight[2]});
            map.put(flight[0], list);
        }
        // It is used to record the minimum cost when flying to the city
        int[] minValues = new int[n];
        Arrays.fill(minValues, Integer.MAX_VALUE);
        // The starting point fee is 0
        minValues[src] = 0;
        // Two queues: record city coordinates and current accumulated expenses
        Queue<Integer> queue = new LinkedList<>();
        Queue<Integer> queueValue = new LinkedList<>();
        queue.offer(src);
        queueValue.offer(0);
        // Record the current number of stations. If it is greater than K, it will jump out directly
        int count = 0;
        int ans = Integer.MAX_VALUE;
        while(!queue.isEmpty()) {
            if(count > K) break;
            int size = queue.size();
            for(int i = 0; i < size; i++) {
                int f = queue.poll();
                int v = queueValue.poll();
                List<int[]> list = map.getOrDefault(f, new ArrayList<>());
                // Traverse the next city you can fly to
                for(int[] nextF: list) {
                    // If the next city is the destination, the minimum cost of updating
                    if(nextF[0] == dst) {
                        ans = Math.min(ans, v+nextF[1]);
                        continue;
                    }
                    // If the cost of flying to the next city is less than the current minimum value, it will be updated; if it is greater than the current minimum value, it will not be put in the queue
                    if(minValues[nextF[0]] > v + nextF[1]) {
                        minValues[nextF[0]] = v + nextF[1];
                        queue.offer(nextF[0]);
                        queueValue.offer(v+nextF[1]);
                    }
                }
            }
            count++;
        }
        // It means that after transferring through station K, you can't fly to the destination and return to - 1
        if(ans == Integer.MAX_VALUE) return -1;
        return ans;
    }
}

Figure 11 on August 21, 2021

27 79. Word search

class Solution {
    int m;
    int n;
    boolean[][]visited;
    public boolean exist(char[][] board, String word) {
      m=board.length;
      n=board[0].length; 
      for(int i=0;i<m;i++){
          for(int j=0;j<n;j++){
              if(board[i][j]==word.charAt(0)){//Search from the first letter
                  visited=new boolean[m][n];
                  if(dfs(board,i,j,1,word)){
                      return true;
                  }
              }
          }
      }
      return false;
    }
    public boolean dfs(char[][]board,int i,int j,int curLen,String word){
        if(i>=m||i<0||j>=n||j<0||curLen>word.length()||board[i][j]!=word.charAt(curLen-1))
            return false;
        if((curLen==word.length())&&board[i][j]==word.charAt(curLen-1))
            return true;
        if(visited[i][j])
            return false;
       // visited[i][j]=true;
        char temp=board[i][j];
        board[i][j]='*';
       // boolean b1,b2,b3,b4;
        boolean b1= dfs(board, i+1, j,curLen+1, word)||
        dfs(board, i-1, j,curLen+1, word)||
        dfs(board, i, j+1,curLen+1, word)||
        dfs(board, i, j-1,curLen+1, word);
       // visited[i][j]=false;
        board[i][j]=temp;
        return b1;
       // Return B1 | B2 | B3 | B4; / / more calculations will be returned here
    }
}

I tried to mark it with the visited array before, but the two pieces of code in the following figure are written backwards, resulting in an error. The following figure is right now

If it is written backwards, it will lead to the backtracking shown in the figure below. One character is used twice

There is a 17ms, which is to compare the number of characters in each of the two strings

public class Solution {
    private char[][] board;
    private char[] word;
    private int m;
    private int n;
    private int targetLen;

    public boolean exist(char[][] board, String str) {
        this.board = board;
        this.m = board.length;
        this.n = board[0].length;
        this.word = str.toCharArray();
        this.targetLen = word.length;
        if(targetLen > m*n){
            return false;
        }
        
        int[] f1 = new int[133];
        int[] f2 = new int[133];
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                ++f1[board[i][j]];
            } 
        }

        for (int i = 0; i < targetLen; i++) {
            ++f2[word[i]] ;
        }

        for (int i = 0; i < 133; i++) {
            if(f1[i] < f2[i]) {
                return false;
            }
        }
        
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == word[0]) {
                    boolean[][] visit = new boolean[m][n];
                    boolean res = dfs(i, j, 0,visit);
                    if (res) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    private boolean dfs(int i, int j, int index,boolean [][]visit) {
        if (index == targetLen) {
            return true;
        }
        if (i < 0 || i >= m || j < 0 || j >= n) {
            return false;
        }
        if(visit[i][j]){
            return false;
        }
        if (board[i][j] == word[index]) {
            visit[i][j] = true;
            boolean res = dfs(i - 1, j, index + 1,visit)
                    ||
                    dfs(i + 1, j, index + 1,visit)
                    ||
                    dfs(i, j - 1, index + 1,visit)
                    ||
                    dfs(i, j + 1, index + 1,visit);
            visit[i][j] = false;
            return res;
        }
        return false;
    }
}

28 329. Longest incremental path in matrix

Problem solving idea: enumerate each point and find out the longest increasing path of each point
The code of the first edition is as follows

class Solution {
    int m;
    int n;
    boolean [][]visited;
    int dr[]={0,1,0,-1};
    public int longestIncreasingPath(int[][] matrix) {
        m=matrix.length;
        n=matrix[0].length;
        visited=new boolean[m][n];
        int max=0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                max=Math.max(max,dfs(matrix,i,j,0,-1));
            }
        }
        return max;
    }
    public int dfs(int [][]matrix,int i,int j,int curLen,int last){
        if(i<0||i>=m||j<0||j>=n||matrix[i][j]<=last)
            return curLen;        
        if(visited[i][j])
            return 0;
        visited[i][j]=true;
        int cur=0;
        for(int p=0;p<4;p++){
            int newX=i+dr[p];int newY=j+dr[(p+1)%4];
            int a=dfs(matrix,newX, newY, curLen+1, matrix[i][j]);
            cur=Math.max(cur,a);
        }
        visited[i][j]=false;
        return cur;
    }
}

The code timed out because there are a lot of repeated calculations, but the memo [] [] cannot be used directly. The memo I calculated is directional. It is the maximum length returned by the current element to the previous element when the path of the previous point passes through here, rather than the maximum length that can be obtained from the current point

In fact, the visited array can not be used for this problem. It should be that the problem requires an incremental path. Our judgment conditions will give this conditional condition. If it is not satisfied, it will not be accessed in reverse.

Starting from the current point, we can find the longest increasing path of its adjacent elements smaller than it, and take the largest one

class Solution {
    int m;
    int n;
    int dr[]={0,1,0,-1};
    int maxValue;
    public int longestIncreasingPath(int[][] matrix) {
        m=matrix.length;
        n=matrix[0].length;
        int memo[][]=new int[m][n];   
        int max=0;       
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){                               
                max=Math.max(max,dfs(matrix,i,j,memo));
            }
        }
        return max;
    }
    public int dfs(int [][]matrix,int i,int j,int memo[][]){      
        if(memo[i][j]!=0)
           return memo[i][j];
        memo[i][j]=1;
        int cur=0;
        for(int p=0;p<4;p++){
            int newX=i+dr[p];int newY=j+dr[(p+1)%4];
            if(newX>=0&&newX<m&&newY>=0&&newY<n&&matrix[newX][newY]>matrix[i][j]){
                memo[i][j]=Math.max(memo[i][j],dfs(matrix,newX, newY,memo)+1);
            }           
        }
        return   memo[i][j];
    }
}

reference resources: Longest increasing path in matrix

backtracking in matrix depth first search is often necessary. Because such problems usually require that each element can only be used once, we need to maintain a see matrix (record the accessed elements and repeatedly set the state when dfs presses and returns the stack) However, the state of see is different every time the starting position is selected, resulting in the non reusability of the calculation results (because the calculation results only represent the results in a certain state of see, we can't cache them).
Finally, we can only use backtracking to solve the problem, and the time complexity is exponential. For example, in the classic Word Search II, whether we use a dictionary tree or not, backtracking is inevitable.
The condition that each element of this question can only be used once is implicit - because the (strict) incremental path is required, it is impossible for elements at the same position to appear twice in the effective path. However, the buff brought by the incremental path is more than the previous implicit condition. Because in the inner loop, mat [II] [JJ] > mat [i] [J] It ensures that the previously accessed elements will not appear in the subsequent path at all, so see has no meaning. You can even directly cache the calculation results of each sub call, because no matter where you start the iteration, because there is no state (no see), the calculation results become unique - so they can be cached.

2021.08.22 the 12th natural interesting question

29 121. The best time to buy and sell stocks

Given an array of prices, its ith element prices[i] represents the price of a given stock on day I.

You can only choose to buy this stock one day and sell it on a different day in the future. Design an algorithm to calculate the maximum profit you can make.

Returns the maximum profit you can make from this transaction. If you can't make any profit, return 0.

Solution: to enumerate the profits sold every day, we must find the minimum value before each day

class Solution {
    public int maxProfit(int[] prices) {
        int min=Integer.MAX_VALUE;int max=0;
        for(int i=0;i<prices.length;i++){
            min=Math.min(min,prices[i]);
            max=Math.max(max,prices[i]-min);
        }    
       return max;
    }  
}

30 122. The best time to buy and sell stocks II

class Solution {
    public int maxProfit(int[] prices) {
      int max=0;
      for(int i=1;i<prices.length;i++){
          if(prices[i]-prices[i-1]>0){
              max=max+prices[i]-prices[i-1];
          }
      }  
      return max;
    }
}

Keywords: Algorithm leetcode Interview

Added by mantona on Sun, 31 Oct 2021 16:45:36 +0200