Appearance sequence (Java problem solving dynamic programming + double pointer iteration)

Title Description

Difficulty: medium

Given a positive integer n, the nth item of the appearance sequence is output.

"Appearance sequence" is a sequence of integers. Starting from the number 1, each item in the sequence is a description of the previous item.

You can think of it as a sequence of numeric strings defined by recursive formulas:

  • countAndSay(1) = "1"
  • countAndSay(n) is a description of countAndSay(n-1), which is then converted to another numeric string.

The first five items are as follows:

1.     1
2.     11
3.     21
4.     1211
5.     111221
 The first item is the number 1 
Describe the former item. This number is 1, that is, "a 1", recorded as "11"
Describe the former item. The number is 11, that is, "two 1s", recorded as "21"
Describe the previous item. The number is 21, that is, "a 2" + A "1" is recorded as "1211"
Describe the previous item. The number is 1211, that is, "a 1" + One 2 + The second "1" is recorded as "111221"
To describe a numeric string, first divide the string into a minimum number of groups, each consisting of a continuous maximum of the same characters.
Then, for each group, first describe the number of characters, and then describe the characters to form a description group.
To convert a description to a numeric string, replace the number of characters in each group with a number, and then connect all description groups.

For example, the digital string "3322251" is described as follows:


Example 1:

Input: n = 1
 Output:"1"
Explanation: This is a basic example.

Example 2:

Input: n = 4
 Output:"1211"
Explanation:
countAndSay(1) = "1"
countAndSay(2) = read "1" = One 1 = "11"
countAndSay(3) = read "11" = Two 1 = "21"
countAndSay(4) = read "21" = One 2 + One 1 = "12" + "11" = "1211"

Tips:

1 <= n <= 30

Problem solving analysis

First, read the question to see that countAndSay(n) is the description of countAndSay(n-1), which is in line with the idea of dynamic programming. It can be defined that the state dp[n] is the description of dp[n-1], and the initial value dp[1] = 1;

The state transition equation is DP [n] = description (DP [n-1]); (Description: noun, description)

So how to describe a numeric string according to the topic logic? Here you need to use double pointer + iteration.

Assuming that there is a numeric string 33 222 55 1, we define two pointers i and j of type int;
i is responsible for recording the initial element subscript of each group of elements, such as 33, 0222 and 2;
j is responsible for running forward. If an element equal to i is encountered, it will continue to run forward. If an element equal to i is encountered, it means that a group has been run. At this time, it is necessary to describe the group just run, and switch i to the beginning of the next group of elements, that is, let i equal j at this time;

How to describe it? After running a group, you will find that J - i at this time is the number of elements with subscript i. for example, in the group of 33, i records subscript 0. When J runs to 2, the elements represented by i and j are not equal, so the number of elements with subscript i is j - i = 2;

For another example, in the 222 group, i records subscript 2. When J runs to 5, the elements represented by i and j are not equal, so the number of occurrences of elements with subscript i is j - i = 3;

After running a group, let i = j to point i to the beginning element of the next group.

Since we only use dp[n] and dp[n-1] in the whole process, we can use the rolling array to optimize the length of dp String[] dp = new String[2];

Problem solving code

public String countAndSay(int n) {
        String[] dp = new String[2]; // Define status
        dp[1] = "1";  // boundary
        
        for (int i = 2 ; i <= n ; i++){ // dp[i] description dp[i-1]
            dp[i & 1] = description(dp[(i - 1) & 1]);	// & 1 == % 2
        }
        return (n & 1) == 1 ? dp[1] : dp[0];
    }

	// Description numeric string
    public String description(String temp){
        StringBuilder builder = new StringBuilder();
        int i = 0 , j = 0;       // Double pointer run string

        char a = temp.charAt(0);        // Initializes the character where i is located
        char b = '0';                   // Initialize the character where j is located

        while (j < temp.length()){      // Using build to describe temp
            b = temp.charAt(j);

            if(a == b){             // j encountered an unequal number of additions and characters in the previous run. Switch i to j's position, a to b, representing the beginning of a new group
                j++;
            }else {
                builder.append(j - i).append(a);    // Describe the group you ran
                i = j++;		// Complete group switching
                a = b;
            }
        }
        builder.append(j - i).append(a);   // j will cross the boundary, and the last group cannot be described, so the last group is processed separately
        return builder.toString();
    }

summary

This method is very efficient. If it is understandable, it is still relatively easy. If it is difficult to understand, it can be completed by typing a table, that is, list all the possibilities, and then directly look up the table. For details, you can go to the leetcode official solution of this problem;



Years are long, and decay only affects the skin; If enthusiasm is abandoned, decadence will lead to soul

Tags: Java Algorithm leetcode Dynamic Programming

Posted on Thu, 14 Oct 2021 23:48:24 -0400 by rathersurf