【Leetcode】Dynamic programming training (8)

413. Arithmetic Sequence Division

Click to view: arithmetic sequence division


If a sequence has at least three elements and the difference between any two adjacent elements is the same, the sequence is said to be an arithmetic sequence.
For example, [1,3,5,7,9], [7,7,7,7], and [3,-1,-5,-9] are arithmetic progressions.
Given an integer array nums, return the number of subarrays in the array nums that are arithmetic arrays.
A subarray is a contiguous sequence in an array.

Example 1:
Input: nums = [1,2,3,4]
Output: 3
Explanation: There are three subarrays in nums: [1, 2, 3], [2, 3, 4] and [1,2, 3,4] itself.
Example 2:
Input: nums = [1]
Output: 0


state transition equation

dp[i]: Indicates the number of arithmetic progressions in all subarrays ending with the i position element


If ABCD is an arithmetic sequence, and D and BC can also form an arithmetic sequence, ABCDE is also an arithmetic sequence


If you want to find the number of arithmetic series of all sub-arrays ending with i,
and the sub-arrays are continuous, if you want to form an arithmetic series, at least position i and positions i-1 and i-2 form an arithmetic series


dp[i] is divided into two cases

Case 1: i i-1 i-2 position elements can form an arithmetic progression

Suppose the element at position i-2 is a, the element at position i-1 is b, and the element at position i is c,
then the difference between the three is the same, that is, cb==ba

v The arithmetic sequence ending with ab, since c and ab can also form an arithmetic sequence, so ending with abc is also an arithmetic sequence,
and ending with ab is equivalent to ending with b, that is, dp[i-1] (The number of all arithmetic sequences ending at i-1 position)
and abc belongs to the arithmetic sequence and is not in the case of dp[i-1], so +1 is required

In this case: dp[i]=dp[i-1]+1


Case 2: i i-1 i-2 position elements do not constitute an arithmetic progression

Suppose the element at position i-2 is a, the element at position i-1 is b, and the element at position i is c,
then the difference between the three is different , that is, cb is not equal to ba

Because the sub-arrays are continuous, and abc does not constitute an arithmetic sequence, it is meaningless if the previous structure does not constitute an arithmetic sequence. In
this case: dp[i]=0


The state transition equation is:
dp[i]= cb==ba?dp[i-1]+1:0

full code

class Solution {
    
    
public:
    int numberOfArithmeticSlices(vector<int>& nums) {
    
    
         int n=nums.size();
         vector<int>dp(n,0);
         int i=0;
         int sum=0;
         for(i=2;i<n;i++)
         {
    
    
             //状态转移方程
             dp[i]=nums[i]-nums[i-1]==nums[i-1]-nums[i-2]?dp[i-1]+1:0;
             sum+=dp[i];
         }
         //返回dp表中所有值之和
         return sum;
    }
};

Since the arithmetic sequence requires at least three elements, when there are only one/two elements, the requirements are not met, so dp[0]=0 dp[1]=0

978. Longest Turbulent Subarray

Click to view: Longest Turbulent Subarray

Given an integer array arr, return the length of the largest turbulent subarray of arr.
A subarray is a turbulent subarray if the comparison sign is flipped between each adjacent pair of elements in the subarray.
More formally, we call a subarray of arr a turbulent subarray when A[i], A[i+1], ..., A[j] satisfy only the following conditions: if i <= k
< j :
when k is odd, A[k] > A[k+1], and
when k is even, A[k] < A[k+1];
or if i <= k < j :
when k When k is even, A[k] > A[k+1], and
when k is odd, A[k] < A[k+1].

Example 1:
Input: arr = [9,4,2,10,7,8,8,1,9]
Output: 5
Explanation: arr[1] > arr[2] < arr[3] > arr[4] < arr[5]
Example 2:
Input: arr = [4,8,12,16]
Output: 2


topic analysis

If the value of B is larger than A, it will show an upward trend. If
the value of C is smaller than B, it will show a downward trend. If
the value of D is larger than C, it will show an upward trend.
Then the ABCD array is a turbulent sub-array.

state transition equation

dp[i]: Indicates the length of the longest turbulent array among all subarrays ending at position i

I just started to analyze and write dp[i], but I will find that the turbulent array has a rising and falling trend, and dp[i] cannot be solved, so define f[i] and g[i] again


f[i]: Indicates the length of the longest turbulent array that finally shows an upward trend among all sub-arrays ending at position i


g[i]: Indicates the length of the longest turbulent array that finally shows a downward trend among all sub-arrays ending at position i


f[i] state transition equation

Suppose the value of the element at position i-1 is a, and the value of the element at position i is b


Case 1 a>b

Combining with the previous array can only show a downward trend
. If you want to show an upward trend yourself, a single sub-array can be formed. The last position can either rise or fall, that is,
f[i]=1


Case 2 a<b

At this time, there is an upward trend, in line with the meaning of f[i]

Look again for the longest length of the turbulence array that ends at position i-1 and finally shows a downward trend, that is, g[i-1]
plus the length from a to b, that is, +1 .
In this case: f[i]= g[i-1]+1


Case 3 a==b

In this case, if you want to make the i position show an upward trend, you can only form a sub-array with one alone,
that is, f[i]=1

g[i] state transition equation

Suppose the value of the element at position i-1 is a, and the value of the element at position i is b


Case 1 a>b

At this time, it is showing a downward trend, which is in line with the meaning of g[i]

Look again for the longest length of the turbulence array that ends at position i-1 and finally shows an upward trend, namely f[i-1]
plus the length from a to b , namely +1

In this case: g[i]=f[i-1]+1


Case 2 a<b

In this case, if you want to make the i position show a downward trend, you can only form a sub-array with one,
that is, g[i]=1


Case 3 a==b

In this case, if you want to make the i position show a downward trend, you can only form a sub-array with one,
that is, g[i]=1

full code

class Solution {
    
    
public:
    int maxTurbulenceSize(vector<int>& nums) {
    
    
       int n=nums.size();
       //f g表 都表示湍流数组的最长长度
       //而单独一个数本身,表示最低长度为1
       //所以f/g 最差长度也为1
       vector<int>f(n,1);
       vector<int>g(n,1);

       int i=0;
       //单独一个数 返回1 ,所以初始值为1
       int fmax=1;
       int gmax=1;
       for(i=1;i<n;i++)
       {
    
    
           //f[i] a<b情况
           if(nums[i-1]<nums[i])
           {
    
    
               f[i]=g[i-1]+1;
           }
           //g[i] a>b情况
           else if(nums[i-1]>nums[i])
           {
    
    
               g[i]=f[i-1]+1;
           }
           fmax=max(fmax,f[i]);
           gmax=max(gmax,g[i]);
       }
       //返回 f和g表中的最大值
       return max(fmax,gmax);
    }
};

A single number itself can constitute an upward or downward trend, so the length of the turbulence array is at worst 1, so all the elements in the f/g table
can be initialized to 1

139. Word Splitting

Click to view: word splitting


Given a string s and a list of strings wordDict as a dictionary. Please judge whether s can be spliced ​​out of words that appear in the dictionary.
Note: It is not required to use all the words in the dictionary, and the words in the dictionary can be used repeatedly.

Example 1:
Input: s = “leetcode”, wordDict = [“leet”, “code”]
Output: true
Explanation: Return true because “leetcode” can be concatenated from “leet” and “code”.
Example 2:
Input: s = “applepenapple”, wordDict = [“apple”, “pen”]
Output: true
Explanation: Return true because “applepenapple” can be concatenated from “apple” “pen” “apple”.
Note that you can reuse words in the dictionary.
Example 3:
Input: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”]
Output: false

state transition equation

dp[i]: Indicates whether the string in the interval [0,i] can be spliced ​​by the words in the dictionary. If it
can be spliced, it will return true, if not, it will return false

Divide the question according to the last position


If it can be determined that the previous part can be spliced ​​successfully, and the last word is guaranteed to be in the dictionary, the entire string can be spliced.

Let j be the starting position of the last word,
the range of subscript j is 0<=j<=i
0 means the whole string as the last word
i means the last character as the last word


The starting position of the string is 0
j as the starting position of the last word, so the ending position of the string is j-1

The strings in the interval [0,j-1] need to be judged whether they can be spliced ​​by words in the dictionary, that is, the range of the last word in dp[j-1]
is [j,i], the substrings in this interval is in the dictionary


The state transition equation is:
when dp[i-1] is true and the last word (within [ji]) satisfies both in the dictionary, the result is true; if any one is not true, it is
false

initialization

When j is 0, an out-of-bounds problem occurs

In order to prevent this kind of out-of-bounds problem, a virtual node is added to
the expanded array. The subscript of the virtual node is 0, and the element subscript of the original array starts from 1.


If j is 0, it means that the entire range from 0 to i is regarded as the last word. If the last word is in the dictionary, true should be returned.
dp[0]=true
can ensure that both are true


Assuming that the original string is s, the auxiliary position is generally a space
s=' ' +s
After the original string is added with the auxiliary position, the original string is equivalent to counting from 1, which just corresponds to the new dp table

full code

class Solution {
    
    
public:
    bool wordBreak(string s, vector<string>& wordDict) {
    
    
        unordered_set<string>hash;
        for(auto& s:wordDict)
        {
    
    
           hash.insert(s);
        }
         int n=s.size();
         //为了防止越界问题,所以多加一个虚拟节点
         vector<bool>dp(n+1);
         //初始化
         dp[0]=true;
         s=' '+s;//使原始字符串的下标统一+1
         int i=0;
         int j=0;
         for(i=1;i<=n;i++)
         {
    
    
             for(j=i;j>=1;j--)
             {
    
    
                 //在hash中判断 s中对应的子串在不在 若在返回1 不在返回0
                 if(  dp[j-1]&&  hash.count(s.substr(j,i-j+1)) )
                 {
    
    
                     dp[i]=true;
                     break;//找到一种情况即可
                 }
             }
         }
         //因为多加了个虚拟节点,所以下标+1
         return dp[n];
    }
};

Guess you like

Origin blog.csdn.net/qq_62939852/article/details/131491530