# [Day11] three times a day

## subject

### NC58 finds two switching nodes (esay) in the binary search tree

#### describe

A binary tree was originally a search binary tree, but two nodes changed their positions, so that the binary tree is no longer a search binary tree. Please output the values of the two wrong nodes in ascending order. (each node has different values)

Search Binary Tree: the left child node of each node is smaller than the current node, and the right child node is larger than the current node.

Input:{4,2,5,3,1} Return value:[1,3]

#### reflection

When we see a binary search tree, we naturally think of its nature, that is, after traversing the middle order, the arrangement of nodes is orderly

Then, for the case described in the title, the result of order traversal is an ordered array in which two elements are exchanged (in fact, it is not ordered after exchange)

The topic becomes "find the two elements in the swapped position in an ordered array"

In fact, there is a fixed solution to this problem. You can understand it by yourself:

It is suggested that when understanding this code, you can write several examples of ordered arrays swapped for two elements on the draft paper

public static int[] getTwoSwap(int[]arr) { int[] res = new int[2]; int first=-1; int second=-1; for (int i = 0; i < arr.length - 1; i++) { if (arr[i]>arr[i+1]) { if (first==-1) { first=i; second=i+1; } else { second=i+1; } } } res[0]=first; res[1]=second; return res; }

The rest is the middle order traversal

#### Problem solution

public class NC58_findError { // Called main function public int[] findError (TreeNode root) { List<Integer> nums = new ArrayList<>(); dfs(nums,root); return findErr(nums); } // Gets the sequence traversed in the middle order public void dfs(List<Integer>nums,TreeNode root) { if (root==null) return; dfs(nums,root.left); nums.add(root.val); dfs(nums,root.right); } // Find the two elements in the ordered array that are swapped public int[] findErr(List<Integer>nums) { int[] res = new int[2]; int first = -1; int second = -1; for (int i = 0; i < nums.size()-1; i++) { if (nums.get(i)>nums.get(i+1)) { if (first==-1) { first=i; second=i+1; } else { second=i+1; } } } res[0]=nums.get(second); res[1]=nums.get(first); return res; } }

### NC142 longest repeating substring (medium)

#### describe

A duplicate string is formed by splicing two identical strings. For example, abcabcabcabcab * * C is a duplicate string with a length of 6, while abcbaabcba does not have a duplicate string.

Given a string, return the length of its longest repeating substring.

Returns 0 if there are no duplicate character substrings.

The definition of substring in this question is a continuous interval in the string.

Example:

Input:"ababc" Return value: 4 explain: abab Is the longest repeating character substring with a length of 4

Input:"abcab" Return value: 0 Description: the string has no duplicate character substring

#### reflection

Method 1: violence algorithm

The outer loop defines the length of the string (1-n). Of course, our length can be enumerated from large to small, so that we can return as long as the answer appears, reducing the number of judgments

The inner layer defines the starting position of the string. The record can have at most several duplicate strings from the current starting position

#### Problem solution

public class NC142_solve { public static void main(String[] args) { NC142_solve solu = new NC142_solve(); System.out.println(solu.solve("abcabcab")); } public int solve (String a) { if (a.length()<=1) return 0; // The size cannot exceed half of the original string // The string length is enumerated from large to small, so as long as the answer appears, we can return it directly for (int size = a.length()/2; size >=1 ; size--) { // The second level loop enumerates the starting position for (int start = 0; start < a.length() - size; start++) { String currSub = a.substring(start, start+size); int l=start+size,r=l+size-1; int count=1; // count must be at least 2 to indicate at least one repetition while (r<a.length()) { if (!currSub.equals(a.substring(l,r+1))) break; count++; l=r+1; r=l+size-1; } //if (count>1) res=Math.max(res,count*size); if (count>1) return count*size; } } return 0; } }

### NC144 non adjacent maximum subsequence sum (medium)

#### describe

Give you an array with a length of n and select a subsequence. Any two numbers in the subsequence cannot have adjacent subscripts (subsequence can be empty)

The subsequence of this question refers to an array composed of several numbers arbitrarily selected from the array.

#### reflection

Our first reaction to this question is the dynamic gauge. Its sub state is: either the current position is not selected, consistent with the previous position, or the current position is selected, then dp[k]=dp[k-2]+arr[k]

The state transition equation can be written as follows:

DP [k] = max (DP [k-1], DP [k-1] + arr [k]) < which is larger in the current position or not >

#### Problem solution

public long subsequence (int n, int[] array) { if (array.length==1) return new Long(Math.max(0,array[0])); if (array.length==2) return new Long(Math.max(0,Math.max(array[0],array[1]))); long[] dp = new long[n]; dp[0]=array[0]; dp[1]=array[1]; long res = Math.max(0,Math.max(dp[0], dp[1])); for (int i = 2; i <n ; i++) { dp[i]=Math.max(dp[i-1],dp[i-2]+array[i]); res=Math.max(res,dp[i]); } return new Long(Math.max(0,res)); }

In the above code, we can find that only the previous and previous elements of dp are used each time, so we can optimize the dp array without

The optimized code is as follows:

public long subsequence (int n, int[] array) { if (array.length==1) return new Long(Math.max(0,array[0])); if (array.length==2) return new Long(Math.max(0,Math.max(array[0],array[1]))); long pre = array[0]; long curr = array[1]; long res = Math.max(0,Math.max(pre,curr)); for (int i = 2; i <n ; i++) { long newPre = Math.max(curr, pre + array[i]); res=Math.max(res,newPre); pre=curr; curr=newPre; } return new Long(Math.max(0,res)); }