Leetcode question brushing diary: 11-15 questions

Posted by malikah on Sun, 02 Jan 2022 14:29:47 +0100

brief introduction

The author graduated from Xi'an Jiaotong University in 2021 and will continue to study postgraduate in this university in September of the same year. After experiencing the intense and exciting job search process of some students around him, the 60w + offer and 30w offer are greatly related to his ability to tear the code by hand. Therefore, the author is determined to brush Leetcode from scratch to improve his code ability, Lay a good foundation for finding a job or further study after graduation
This series will be Leetcode's question brushing record post. According to the order of the question bank, every five questions will be one post. The main purpose is to make your own records and summary. However, if any students or friends see this post and help, it will also be an extra joy and encouragement!

Title:

Xi Container with the most water

Give you n nonnegative integers a1, a2,..., an, each representing a point (i, ai) in the coordinate. Draw n vertical lines in the coordinates. The two endpoints of the vertical line i are (i, ai) and (i, 0). Find the two lines so that the container formed by them and the x-axis can hold the most water.

Example 1:

Input: [1,8,6,2,5,4,8,3,7]
Output: 49
Explanation: the vertical line in the figure represents the input array [1,8,6,2,5,4,8,3,7]. In this case, the maximum value that the container can hold water (represented by the blue part) is 49.

Solution:

class Solution {
public:
    int maxArea(vector<int>& height) {
        //Define two pointers to the head and tail respectively
        int head=0,tail=height.size()-1;
        //Calculate the area of the initial container with the head and tail as the bottom edge
        int maxarea=min(height[head],height[tail])*(tail-head);
        while(tail>head){
            //Comparing the length of the edges of two pointers, it is easier to get a large area by keeping the high one
            if(height[head]>height[tail]) tail-=1;
            else head+=1;
            int tmparea=min(height[head],height[tail])*(tail-head);
            maxarea=max(tmparea,maxarea);
        }
        return maxarea;

    }
};

Idea: Double pointers. Initially, the container is composed of head and tail, and then move the pointer. Since the change of the bottom edge is the same for each grid of head or tail, it is more conducive to obtain a larger container by comparing the two edges and moving the shorter one. The condition for the end of the cycle is tail pointer > head pointer

12, Integer to Roman numeral

Roman numerals contain the following seven characters: I, V, X, L, C, D and M.

characterValue
I1
V5
X10
L50
C100
D500
M1000

Usually, the small Roman numerals are to the right of the large ones. But there are also special cases. For example, 4 is not written as IIII, but IV. The number 1 is on the left of the number 5, and the number represented is equal to the value 4 obtained by subtracting the decimal 1 from the large number 5. Similarly, the number 9 is represented as IX. This special rule applies only to the following six cases:

  • I can be placed to the left of V (5) and X (10) to represent 4 and 9.
  • X can be placed to the left of L (50) and C (100) to represent 40 and 90.
  • C can be placed to the left of D (500) and M (1000) to represent 400 and 900.

Give you an integer and convert it to Roman numerals.

Example:

Input: num = 3
Output: "III"

Solution:

class Solution {
public:
    string intToRoman(int num) {
        string ans;
        //Using two arrays, corresponding to the same I, [i] and chara[i] correspond to each other
        //Use reverse order to conform to the output form
        //When the array length is known, using an array instead of a vector can reduce memory consumption
        int value[13]={1000,900,500,400,100,90,50,40,10,9,5,4,1};
        string chara[13]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};

        int i=0;
        while(num>0){
            if(num>=value[i]){
                ans=ans+chara[i];
                //Subtraction is used instead of division
                num-=value[i];
            }
            else i++;
        }
        return ans;
    }
};


Idea:
For a number 2100, first judge whether it is greater than 1000. If it is greater than 1000, put "M" into the ans tail, then subtract 1000 from this number, ok, and then subtract 1000. Then put an "M" into the ans tail, subtract 1000, leaving 100. Judge whether it is greater than 900, 500 and 400 until 100. Put a "C" into the ans tail, subtract 100, leaving 0. The cycle ends
94% in execution time and 97% in memory consumption

Summary:
1. When the amount of data is known, using array instead of vector < > can effectively reduce memory consumption

13, Roman numeral to integer

Subject conditions are as in question 12. It is required to input a Roman numeral and output the corresponding integer

Example:

Input: "III"
Output: 3

Solution:

class Solution {
public:
    int romanToInt(string s) {
        int ans=0;
        unordered_map<string,int> mymap={{"I",1},{"IV",4},{"V",5},{"IX",9},{"X",10},{"XL",40},{"L",50},{"XC",90},{"C",100},{"CD",400},{"D",500},{"CM",900},{"M",1000}};

        int i=0;
        while(i<s.size()){
            //Judge whether there are numbers such as 4 and 9
            if(mymap.find( s.substr(i,2) )!=mymap.end() ){
                ans+=mymap[s.substr(i,2)]; 
                i+=2;
                //Note continue
                continue;
            }
            else{
                ans+=mymap[s.substr(i,1)];
                i++;
            }
        }
        return ans;
    }
};

Idea: use hashmap to store the correspondence. For example, for IV, first judge whether there are numbers such as 4 and 9. Therefore, find() for s.substr(i,i+2) and the result is 4. If you judge a single character first, you will get 1 + 5 = 6, which is an error

Summary:
1. The parameters of the find() function cannot be s[i],s[i]+s[i+1], but s.substr(head,length) should be used, because the type of s[i] is char and the type of s.substr(i,1) is string

14, Longest common prefix

Write a function to find the longest common prefix in a string array.

Returns the empty string '' if there is no public prefix.

Example:

Input: strs = ["flower", "flow", "flight"]
Output: "fl"

Solution:

class Solution {
public:
    string longestCommonPrefix(vector<string>& strs) {
        int minlen=INT_MAX;
        int minsubstr;
        for(int i=0;i<strs.size();i++)
            if(minlen>strs[i].size() ){
                //Record the length of the minimum string for the boundary conditions of the following loop
                minlen=strs[i].size();
                //Record the sequence number of the smallest string. When no different characters appear at the end of the cycle, the shortest string is the answer
                minsubstr=i;
            }
        for(int i=0;i<minlen;i++){
            for(int j=0;j<strs.size();j++){
                //As long as different characters appear, it ends immediately and returns the substring at this time
                if(strs[j][i] != strs[0][i])
                    return strs[0].substr(0,i);
            }
        }
        return strs[minsubstr];
    }
};

Idea: compare the ith character of each string. If they are all the same, i will be added by one until they are different. At this time, i is the length of the longest prefix. You can output the first i characters of any string

15, Sum of three

Give you an array num containing n integers. Judge whether there are three elements a, b and c in num, so that a + b + c = 0? Please find all triples with sum 0 and no repetition.

Note: the answer cannot contain duplicate triples.

Example 1:

Input: num = [- 1,0,1,2, - 1, - 4]
Output: [- 1, - 1,2], [- 1,0,1]]

Example 2:

Input: num = [0,0,0,0]
Output: [[0,0,0]]

Solution:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int> > ans;
        sort(nums.begin(),nums.end());
        for(int i=0;i<nums.size();i++){
            if(i>0 && nums[i]==nums[i-1]) continue;
            int head=i+1,tail=nums.size()-1;
            while(head<tail){
                if(head>i+1 && nums[head]==nums[head-1]){
                    head++;
                    continue;
                } 
                int sum=nums[head]+nums[tail]+nums[i];
                if(sum<0)
                    head++;
                if(sum>0)
                    tail--;
                if(sum==0){
                    ans.push_back({nums[i],nums[head],nums[tail]});
                    head++;
                }
            }
        }
        return ans;
    }
};

Idea: the double pointer solution is used. The comparison between the core code of the double pointer and the traditional solution is as follows:

//This is a double pointer
while(head<tail){
    if(sum<0)
        head++;
    if(sum>0)
        tail--;
    if(sum==0)
        //...
}
//This is a common way of writing
for(int i=0;i<m;i++)
    for(int j=0;j<n;j++){
        if(sum==0)
            //...
}

It can be seen that double pointers convert a two-layer loop into a one-layer loop, and the time complexity has changed from n^2 to N. so how to realize the conversion from common writing to double pointer writing?
Generally speaking, when you need to repeatedly traverse an array, you can think of using the double finger needle method
To say pointer is actually to set two int variables to be assigned to the beginning and end of the array respectively. In one layer of loop, only one pointer is moved each time. Finding the condition to judge the movement of the pointer is the core of the double pointer. In this problem, it is a problem that the sum is 0. When sum > 0, it obviously indicates that the overall value is too large and should be made smaller, Therefore, for the sorted array, move the tail pointer to the left. Obviously, the size of sum and 0 is the condition for judging the pointer movement in this question

notes

Title Source: LeetCode
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.

The copyright of blog belongs to the author. For commercial reprint, please contact the author for authorization, and for non-commercial reprint, please indicate the source.

Topics: C++ Algorithm data structure leetcode