Algorithm intermediate learning 1

Keywords: Algorithm

1, Observation table method

Xiaohu went to a nearby store to buy apples. The treacherous vendor used bundling transactions and only provided 6 packages per bag and 8 packages per bag. But now Xiaohu only wants to buy exactly n apples. Xiaohu wants to buy as few bags as possible for easy carrying. If you can't buy exactly n apples, Xiaohu won't buy them. Enter an integer n, indicating the apples Xiaohu wants to buy, and return the minimum number of bags used. If it cannot be installed exactly anyway, return - 1

/**
 * @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");
            }
        }
    }

    /**
     * Bags are divided into 8 and 6. If you want to minimize the number of bags, 8 is preferred
     * So first get the number of 8 bags in m/8, and then calculate the number of apples left
     * Check whether the remaining apple trees can be divided by 6. If so, the total number of bags is equal to bag8 + bag6
     * No, you can count the number of 8 bags - 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, representing n points arr[0], arr[1]...arr[n-1] from left to right on the number axis, and a positive number L, representing a rope with length L, it is found that the rope can cover at most several points.

/**
 * Slide the window so that left goes straight to the right
 * First make the starting point of the rope at ar[0] and mark it as L, and then extend the rope to see if it can reach the next point arr[1] until it can not be extended
 * When elongation is not possible, 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, Pretreatment method

Niuniu has some squares in a row. Each square has been dyed red or green. Niuniu can now select any square and dye it with either of these two colors. The color of the square will be covered.

The goal of Niuniu is that after dyeing, each red R is closer to the left than each green G.

Niuniu wants to know how many squares he needs to paint at least.

As shown in the example: s = RGRGR. After painting and dyeing, we become RRRGG, which meets the requirements. The number of painting and dyeing is 2. There is no better painting and dyeing scheme

/**
 * @Author: Gao Yubo
 * @Date: 2021/11/18 16:38
 */
public class Color {
    public static void main(String[] args) {
        System.out.println(minColorCount("RGRGR"));

    }

    /**
     * Pretreatment method
     * Change the left side to R and the right side to G
     * Therefore, try from left to right position by position, such as changing the left of 0 to R, and [0,n-1] to G
     *                           1 The left of becomes R and [1, n-1] becomes G
     * In order to find the minimum chromatic number, we need to know how many G in the left range and how many R in the right range
     * That is, how many G's are there in [0,i] and how many R's are there in [I, n-1]
     * With these two results, you can traverse and constantly 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;
        //Pretreatment
        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, Equal probability return

Given a function f, it can return a number of 1 ~ 5 with equal probability. Please process 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 equal to 0-6 equal probability + 1
        For binary representation, 3 bits are required, which can be expressed to 0-7,
        So we need a method that can return 0 and 1 with equal probability,
        Use this method three times, and then splice it together to form a decimal number. If the last is 7, reuse it three times.
        In this way, you can get the equal probability of 0-6, 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;
    }

    /**
     * Equal probability returns 0 and 1
     * Return 1-5:12345 using equal probability
     * Greater than 3 returns 1, less than 3 returns 0, equal to three, reuse
     */
    public static int getRandom01(){
        int random01 = 0;
        do {
            random01 = getRandom5();
        }while (random01 == 3);

        return random01 > 3?1:0;
    }
    
}

5, Bracket matching

Question 1

How many extra parentheses are needed to keep the parentheses of a string matching correctly

/**
 * @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);
            //odd
            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 left parenthesis + +, right parenthesis--
     * In the process, if count < 0, it indicates that a separate right parenthesis appears, and an left parenthesis is required at this time
     * After traversal, if count > 0, there are too many left parentheses and so many right parentheses are needed
     */
    public static int needParentheses(String str){
        char[] chars = str.toCharArray();
        //In the current state, < 0 represents missing '('
        int count = 0;
        //How many extra parenthesis characters are required
        int res = 0;
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] == '('){
                count++;
            }
            //Right parenthesis encountered
            else {
                //count--;
                //if (count < 0){
                //    //Add an open parenthesis
                //    res++;
                //    count = 0;
                //}
                if (count == 0){
                    res++;
                }else {
                    count--;
                }
            }
        }
        return res+ count;
    }
}

Question 2

Maximum depth of bracket string

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;
}

6, magic Set move

Give a set a containing n integer elements and a set b containing m integer elements. Define magic operation as taking an element from one set and putting it into another set, and the average value of each set after operation is greater than that before operation. Note the following two points:

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

2) The element with value x is taken out from set b and put into set a, but there are already elements with value x in set a, then the average value of a remains unchanged (because the set elements will not be repeated), and the average value of b may change (because x is taken out)
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 value of the two sets increases
     * 1.Ensure that the moved element 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 values to sets
            largeList = arr1;
            smallList = arr2;
            largeSum = sum1;
            smallSum = sum2;
        }
        else {
            //Assign values to sets
            largeList = arr2;
            smallList = arr1;
            largeSum = sum2;
            smallSum = sum1;
        }
        int largeSize = largeList.length;
        int smallSize = smallList.length;
        int result = 0;
        HashSet<Integer> 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 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 conversion

Convert the given number into a string according to the following principles: 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", and the number is 5,

Write a function that gives the number of different 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;
        }
        //The current index bit is used as a letter
        int res = convert(arr,index+1);
        //The two index bits are combined into letter rules 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];
    }
}

8, Stack sorting

Please write a program to sort the integer data in a stack in ascending order (that is, the data in the stack is unordered before sorting, and the largest element is at the top of the stack after sorting). It is required that only one additional element can be used at most
The stack stores temporary data, but elements cannot be copied to other data structures.

public static void sortWithStack(Stack<Integer> stack){
    Stack<Integer> help = new Stack<Integer>();
    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 the stack
    while (!help.isEmpty()){
        stack.add(help.pop());
    }
    while (!stack.isEmpty()){
        System.out.print(stack.pop()+" ");
    }
}

9, Binary tree weight

Each node of a binary tree has an int weight. Given a binary tree, it is required to calculate the maximum value of the weight and in 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;
    }
}

Posted by johnrcornell on Tue, 30 Nov 2021 14:46:44 -0800