# The observation table method

Xiaohu went to a nearby store to buy apples, and the treacherous merchant used a bundled deal, only offering 6-per-bag and 8-per-bag packages that could not be split. But Xiaohu now only wants to buy exactly n apples, and Xiaohu wants to buy as few bags as possible for easy carrying. If it cannot buy exactly n apples, Xiaohu will not buy it. Enter an integer n, which represents the number of apples Xiaohu wants to buy, and returns the minimum number of bags used. Returns -1 if it doesn't fit in anyway

```
/**
* @Author: Gao Yubo
* @Date: 2021/11/18 14:19
*/
public class Bag {
public static void main(String[] args) {
for (int i = 1 ; i < 100; i ++){
if (minBags(i) != minBag1(i)){
System.out.println(i+" no");
}
}
}
/**
* The bags are divided into 8 and 6. If you want to minimize the number of bags, 8 is preferred.
* So first m/8 comes out with several 8 bags, and then calculate the number of remaining apples
* Check if the remaining apple trees are divisible by 6, if the total number of bags is equal to bag8 + bag6
* If it is not possible, set the number of 8 bags to -1, then calculate the remaining apple trees and then judge bag6,
* When bag8 is reduced to 0 or the remaining apples are >24, there is no need to continue (because >24 must give priority to bag8)
*/
public static int minBags(int m){
if ((m & 1)!= 0){
return -1;
}
if (m == 6 || m == 8){
return 1;
}
int bag6 = -1;
int bag8 = m / 8;
int rest = m - 8 * bag8;
while (rest < 24 && bag8 >= 0){
bag6 = rest % 6 == 0 ? rest/6: -1;
if (bag6 != -1){
return bag8 + bag6;
}
bag8--;
rest = m - (bag8 * 8);
}
return -1;
}
/**
* Observation table method
*/
public static int minBag1(int m){
if ( (m & 1) != 0){
return -1;
}
if (m < 18){
switch (m){
case 6:
case 8:
return 1;
case 12:
case 14:
case 16:
return 2;
default:
return -1;
}
}
return ((m - 18) / 8) + 3;
}
}
```

# 2. Sliding window

Given an ordered array arr, it means that there are n points arr[0], arr[1]…arr[n-1] from left to right on the number axis, and a positive number L is given, which means that a length of For the rope of L, find the maximum number of points the rope can cover.

```
/**
* Slide the window, let the left go all the way to the right
* First let the starting point of the rope be at ar[0], denoted as L, then stretch the rope to see if it can reach the next point arr[1], until it can't be stretched
* When it cannot be stretched, update max, L++, until the end of arr
*/
public static int maxCount(int []arr,int L){
int left = 0;
int count = 0;
int max = Integer.MIN_VALUE;
//int count = 0;
for (left = 0; left < arr.length; left++){
count = 0;
while (left+count < arr.length && arr[left+count] - arr[left] <= L){
count++;
}
//update max
max = Math.max(count,max);
}
return max;
}
```

# 3. Preprocessing method

Niu Niu has some squares lined up in a row. Each square has been dyed red or green. Niu Niu can now choose any square and dye it with either of these two colors, the color of the square will be overwritten.

Niu Niu's goal is that every red R is closer to the left than every green G after the dyeing is done.

Niu Niu wanted to know the minimum number of squares he needed to paint.

As shown in the example: s = RGRGR After we paint, it becomes RRRGG to meet the requirements. The number of paints is 2. There is no better paint scheme than this

```
/**
* @Author: Gao Yubo
* @Date: 2021/11/18 16:38
*/
public class Color {
public static void main(String[] args) {
System.out.println(minColorCount("RGRGR"));
}
/**
* preprocessing
* Change the left side to R and the right side to G
* So try from left to right position by position, such as changing the left of 0 to R, and [0,n-1] to G
* The left side of 1 becomes R, [1,n-1] becomes G
* To find the minimum coloring number, you need to know how many Gs are in the left range and how many Rs are in the right range
* That is, how many Gs are in [0,i], and how many Rs are in [i,n-1]
* With these two results, you can traverse and update min = [0,i]+[i+1,n-1];
*/
public static int minColorCount(String str){
int i = 0;
char[] chars = str.toCharArray();
int [] leftG = new int[chars.length];
int [] rightR = new int[chars.length];
int min = Integer.MAX_VALUE;
leftG[0] = chars[0] == 'G'?1:0;
rightR[chars.length-1] = chars[chars.length-1] == 'R'?1:0;
// preprocessing
for ( i= 1; i < leftG.length; i++){
leftG[i] = leftG[i-1] + ((chars[i] == 'G')?1:0);
}
for (i = rightR.length-2; i >= 0; i--){
rightR[i] = rightR[i+1] + ((chars[i] == 'R')?1:0);
}
for (i = 0; i < chars.length; i++){
if (i == 0){
min = Math.min(min,leftG[chars.length-1]);
}
else if (i == chars.length-1){
min = Math.min(min,rightR[0]);
}
else {
min = Math.min(min,leftG[i]+rightR[i+1]);
}
}
return min;
}
}
```

# 4. Return with equal probability

## Given a function f, it can return a number with equal probability from 1 to 5. Please process the numbers from 1 to 7 and return a function g with equal probability

```
/**
* @Author: Gao Yubo
* @Date: 2021/11/18 18:24
*/
public class RandomNum {
public static void main(String[] args) {
for (int i = 0; i < 10; i++){
System.out.println(getRandom7());
}
}
public static int getRandom5(){
return (int) (Math.random() * 5) + 1;
}
/**
1-7 equal probability is equivalent to 0-6 equal probability + 1
In binary representation, 3 bits of binary are required to represent 0-7.
So we need a method that can return 0 and 1 with equal probability,
Use this method three times, then join together to form a decimal number, and if it ends up being a 7, use it again three times.
This gives 0-6 equal probability, and then +1 is 1-7
*/
public static int getRandom7(){
int random7 = 0;
do {
int random1 = getRandom01();
int random2 = getRandom01();
int random3 = getRandom01();
random7 = random1 + (random2 << 1)+(random3<<2);
}while (random7 == 7);
return random7 + 1;
}
/**
* Returns 0 and 1 with equal probability
* Returns 1-5 using equal probability: 12345
* greater than 3 return 1, less than 3 return 0 equal to three reuse
*/
public static int getRandom01(){
int random01 = 0;
do {
random01 = getRandom5();
}while (random01 == 3);
return random01 > 3?1:0;
}
}
```

# Five, bracket matching

## Question 1

How many extra parentheses are required to keep the parentheses of the string correctly matched

```
/**
* @Author: Gao Yubo
* @Date: 2021/11/19 16:13
*/
public class NeedParentheses {
public static void main(String[] args) {
for (int i =0 ; i < 20; i++){
String s = randomParentheses(10);
if (needParentheses(s) != needParentheses1(s)){
System.out.println("no");
}
}
}
public static String randomParentheses(int m) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < m; i++) {
int i1 = new Random().nextInt(10);
//strange
if ((i1 & 1) != 0){
stringBuilder.append("(");
}
else {
stringBuilder.append(")");
}
}
return stringBuilder.toString();
}
public static int needParentheses1(String str) {
int leftRest = 0;
int needSolveRight = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '(') {
leftRest++;
} else {
if (leftRest == 0) {
needSolveRight++;
} else {
leftRest--;
}
}
}
return leftRest + needSolveRight;
}
/**
* Set a count variable
* Traverse from left to right. Encountered opening bracket ++, closing bracket --
* If count < 0 in the process, it means that a closing parenthesis appears alone, and a left parenthesis is required at this time
* After the traversal is over, if count > 0, it means that there are too many left parentheses, and so many right parentheses are needed.
*/
public static int needParentheses(String str){
char[] chars = str.toCharArray();
//Current state, <0 means missing '('
int count = 0;
// how many extra bracket characters are needed
int res = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '('){
count++;
}
// encounter closing parenthesis
else {
//count--;
//if (count < 0){
////Add a left parenthesis
// res++;
// count = 0;
//}
if (count == 0){
res++;
}else {
count--;
}
}
}
return res+ count;
}
}
```

## Question 2

Maximum depth of bracketed strings

```
public static int deep(String s) {
char[] str = s.toCharArray();
int count = 0;
int max = 0;
for (int i = 0; i < str.length; i++) {
if (str[i] == '(') {
max = Math.max(max, ++count);
} else {
count=0;
}
}
return max;
}
```

# Six, magic collection mobile

Given a set a with n integer elements and a set b with m integer elements. The magic operation is defined as taking an element from one set and placing it in another set, and the average value of each set after the operation is greater than that before the operation. Note the following two points:

1) You cannot empty the elements of a set, so there is no average

2) The element with the value of x is taken out from the set b and put into the set a, but there is already an element with the value of x in the set a, the average value of a will not change (because the set elements will not be repeated), the average value of b may be changed (because x was taken out)

Q How many magic operations can be performed at most?

```
/**
* @Author: Gao Yubo
* @Date: 2021/11/21 20:57
*/
public class MagicOp {
public static void main(String[] args) {
int[] arr1 = { 1, 2, 5 };
int[] arr2 = { 2, 3, 4, 5, 6 };
System.out.println(magic(arr1, arr2));
}
/**
* After moving elements, ensure that the average of the two sets increases
* 1. The element that is guaranteed to move is not in the target collection
*/
public static int magic(int []arr1,int[]arr2){
double sum1=0,sum2 = 0;
int [] smallList = null;
int [] largeList = null;
double largeSum = 0;
double smallSum = 0;
for (int value : arr1) {
sum1 += value;
}
for (int value : arr2) {
sum2 += value;
}
//average value
double avg1 = getAvg(sum1,arr1.length);
double avg2 = getAvg(sum2,arr2.length);
if ( avg1 == avg2){
return 0;
}
if (avg1 > avg2){
//assign the set
largeList = arr1;
smallList = arr2;
largeSum = sum1;
smallSum = sum2;
}
else {
//assign the set
largeList = arr2;
smallList = arr1;
largeSum = sum2;
smallSum = sum1;
}
int largeSize = largeList.length;
int smallSize = smallList.length;
int result = 0;
HashSet smallSet = new HashSet();
for (int num: smallList){
smallSet.add(num);
}
for (int num: largeList){
double cur = num;
//The moving element is in the middle of the average, and the element does not exist in the target collection
if (cur > getAvg(smallSum,smallSize) && cur < getAvg(largeSum,largeSize) && !smallSet.contains(cur)){
smallSet.add(num);
largeSize--;
largeSum-=num;
smallSum+=num;
smallSize++;
result++;
}
}
return result;
}
private static double getAvg(double sum, int size) {
if (size > 0 ){
return sum/ size;
}
return -1;
}
}
```

# 7. Digital Transformation

Convert the given number to a string, the principles are as follows: 1 corresponds to a, 2 corresponds to b, …… 26 corresponds to z,

For example, 12258 can be converted to "abbeh", "aveh", "abyh", "lbeh" and "lyh", the number is 5,

Write a function that gives the number of distinct strings that can be converted.

```
/**
* @Author: Gao Yubo
* @Date: 2021/11/21 21:36
*/
public class NumberConvert {
public static void main(String[] args) {
int test = 111143311;
char[] arr = String.valueOf(test).toCharArray();
System.out.println(convertDP(arr));
}
public static int convert(char []arr,int index){
if (index == arr.length){
return 1;
}
if (arr[index] == '0'){
return 0;
}
// current index bit as a letter
int res = convert(arr,index+1);
//The combination of two index bits is the letter rule 0-26
if ( (index + 1) < arr.length
&&
((arr[index]-'0')*10 + (arr[index+1]-'0') < 27 )
){
res += convert(arr,index+2);
}
return res;
}
public static int convertDP(char[] arr){
int[] dp = new int[arr.length+1];
dp[arr.length] = 1;
dp[arr.length-1] = arr[arr.length-1] == '0'?0:1;
for (int i = arr.length-2;i >=0; i--){
if (arr[i] == '0'){
dp[i] = 0;
}
else {
dp[i] = dp[i+1];
if ((arr[i] -'0') *10 + (arr[i+1]-'0')<27 ){
dp[i] += dp[i+2];
}
}
}
return dp[0];
}
}
```

# Eight, stack sorting

Please write a program to sort the integer data in a stack in ascending order (that is, before sorting, the data in the stack is unordered, and the largest element is at the top of the stack after sorting), and it is required to use at most one extra

The stack stores temporary data, but must not copy elements into other data structures.

```
public static void sortWithStack(Stack stack){
Stack help = new Stack();
help.add(stack.pop());
//Add the elements in the stack to the auxiliary stack
while (! stack.isEmpty()){
int pop = stack.pop();
while (!help.isEmpty() && pop > help.peek()){
stack.add(help.pop());
}
// Ensure that the bottom of the auxiliary stack is a large element
help.add(pop);
}
// put back on stack
while (!help.isEmpty()){
stack.add(help.pop());
}
while (!stack.isEmpty()){
System.out.print(stack.pop()+" ");
}
}
```

# 9. Binary tree weights

Each node of the binary tree has an int weight. Given a binary tree, it is required to calculate the weight and the maximum value of all paths from the root node to the leaf node.

```
package day12;
/**
* @Author: Gao Yubo
* @Date: 2021/11/21 22:17
*/
public class TreeSum {
public static void main(String[] args) {
Node head = new Node(4);
head.left = new Node(1);
head.left.right = new Node(5);
head.right = new Node(-7);
head.right.left = new Node(3);
System.out.println(getMax(head));
}
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int val) {
value = val;
}
}
public static int getMax(Node node){
if (node == null){
return 0;
}
//leaf node
if (node.left == node && node.right == null){
return node.value;
}
//Left and right node weights
int rightSum = getMax(node.right);
int leftSum = getMax(node.left);
return Math.max(rightSum,leftSum) + node.value;
}
}
```