[leetcode road to brush questions] primary algorithm - array + string

1 array

1.1 [Double Pointer] Delete duplicates in an ordered array

https://leetcode.cn/problems/remove-duplicates-from-sorted-array/

This question uses double pointers. Let’s explain how to use it in combination with the code.

  • i: the position of the array currently traversed
  • j: the current position where the replacement should be performed

At the beginning, both i and j point to the second element of the array (if there are two, there is no direct output of 1), starting from the second position of the array, if the number at this time is the same as the previous (num), then i Continue to traverse backwards until it is different from num. At this time, assign the number at the position of i to the position of j and num, and then move j one bit backward. Repeat the above operation until the last element of the array is traversed.

class Solution {
    
    
public:
    int removeDuplicates(vector<int>& nums) {
    
    
        int length = nums.size();
        int i = 1, j = 1, num = nums[0];
        int ans = 1;
        for(;i<length;i++)
        {
    
    
            if(nums[i] != num)
            {
    
    
                nums[j] = nums[i];
                num = nums[j];
                j++;
                ans++;
            }
            else continue;
        }
        return ans;
    }
};

1.2 [Double pointer] [Greedy] The best time to buy and sell stocks II

https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/

1.2.1 Double pointer

Still continue to use double pointers, low_price refers to the lowest price traversed so far, initially as the first element, high_price refers to the highest price traversed so far, when the highest price is found, it means that a profit has been generated, which is Calculate the profit this time, and modify the values ​​of the two pointers to traverse backwards again until all situations are traversed, but here we also need to consider special circumstances, such as if the stock price is getting lower every day, the final profit should be 0, here A flag is defined to judge this special case.

class Solution {
    
    
public:
    int maxProfit(vector<int>& prices) {
    
    
        int low_price = prices[0];
        int high_price = 0;
        int sum = 0;
        int length = prices.size();
        bool flag = false;
        for(int i=1;i<length;i++)
        {
    
    
            if(prices[i] < low_price) 
            {
    
    
                low_price = prices[i];
                flag = false;
            }
            else
            {
    
    
                high_price = prices[i];
                sum = sum + high_price - low_price;
                low_price = prices[i];
                flag = true;
            }
        }
        if(sum==0 && !flag) return 0;
        else return sum;
    }
};

1.2.2 Greedy

The greedy algorithm is an algorithm that takes the best or optimal (that is, the most favorable) choice in the current state in each step of selection, hoping to lead to the best or optimal result. For this question, we want to make money by buying and selling stocks, so we can divide this problem into several sub-problems. Keep the maximum income within the time. My sub-problem here is to calculate the income every two days. If the income is greater than 0, it will be included in the total income, because the final total income is also the sum of the income greater than 0 in these sub-problems.

class Solution {
    
    
public:
    int maxProfit(vector<int>& prices) {
    
    
       int length = prices.size();
       int sum = 0;
       for(int i=1;i<length;i++)
       {
    
    
           int ssum = prices[i] - prices[i-1];
           if(ssum > 0) sum += ssum;
           else continue;
       }
       return sum;
    }
};

1.3 [Violence] rotation array

https://leetcode.cn/problems/rotate-array/

Violent solution, traversing elements and assigning values ​​one by one, as shown below

class Solution {
    
    
public:
    void rotate(vector<int>& nums, int k) {
    
    
        int n = nums.size();
        vector<int> ans = nums;
        for(int i=0;i<n;i++)
        {
    
    
            nums[(i+k)%n] = ans[i];
        }
    }
};

1.4 [Bit operation] Numbers that appear only once

I think this topic is a bit tricky, because the repeated numbers only appear twice, basically one plus and one minus will disappear, so first sort the array, and then judge whether it is the same as the previous element when traversing, different addition and same subtraction , the last one left is a number that only appears once (it seems to be only suitable for this question)

https://leetcode.cn/problems/single-number/

class Solution {
    
    
public:
    int singleNumber(vector<int>& nums) {
    
    
        sort(nums.begin(),nums.end());
        int n = nums.size();
        int ans = nums[0];
        for(int i=1;i<n;i++)
        {
    
    
            if(nums[i] != nums[i-1]) ans += nums[i];
            else ans -= nums[i];
        }
        return ans;
    }
};

1.5 [Double Pointer] Intersection II of two arrays

https://leetcode.cn/problems/intersection-of-two-arrays-ii/

Double pointers should be the general idea of ​​this question. First sort the two arrays, then define the two pointers to compare the sizes one by one, save the same elements in ans and finally output, but consider the conditions for the end of the traversal. One of After the array is traversed, you can return directly.

class Solution {
    
    
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
    
    
        vector<int> ans;
        sort(nums1.begin(),nums1.end());
        sort(nums2.begin(),nums2.end());
        int n1 = nums1.size();
        int n2 = nums2.size();
        for(int i=0,j=0;i<n1,j<n2;)
        {
    
    
            if(i==n1) return ans;
            if(j==n2) return ans;

            if(nums1[i] > nums2[j]) j++;
            else if(nums1[i] < nums2[j]) i++;
            else
            {
    
    
                ans.push_back(nums1[i]);
                i++;
                j++;
            } 
        }
        return ans;
    }
};

1.6 [Violence] plus one

https://leetcode.cn/problems/plus-one/

For simple carry addition questions, it is enough to traverse from the last element of the array forward, and the decimal is one, but it is necessary to judge whether the first element of the array is full or not.

class Solution {
    
    
public:
    vector<int> plusOne(vector<int>& digits) {
    
    
        int n = digits.size();
        int x = 1;
        for(int i=n-1;i>=0;i--)
        {
    
    
            if(digits[i] + x > 9)
            {
    
    
                digits[i] = digits[i] + x - 10;
                x = 1;
            }
            else
            {
    
    
                digits[i] = digits[i] + x;
                x = 0;
            }
        }
        if(x==1) digits.insert(digits.begin(),1);
        return digits;
    }
};

1.7 [Double Pointer] Move Zero

https://leetcode.cn/problems/move-zeroes/

Use double pointers
(1) index as the currently pointed element, traverse from the beginning, assign a value to the index position every time you find an element that is not zero, and finally assign all original values ​​​​after the index to 0.
(2) Define two pointers left and right. The elements on the left of left are all non-zero, and the elements between left and right are all 0. At the beginning, use right to traverse the array, and left points to 0 elements. When right traverses the elements When not 0, exchange elements with left.

//第一种方法
class Solution {
    
    
public:
    void moveZeroes(vector<int>& nums) {
    
    
        int n = nums.size();
        int index = 0;
        for(int i=0;i<n;i++)
        {
    
    
            if(nums[i]!=0)
            {
    
    
                nums[index] = nums[i];
                index++;
            }
        }
        for(int j=index;j<n;j++)
        {
    
    
            nums[j] = 0;
        }
    }
};

//第二种方法
class Solution {
    
    
public:
    void moveZeroes(vector<int>& nums) {
    
    
        int n = nums.size();
        int left = 0 , right = 0;
        while(right < n)
        {
    
    
            if(nums[right])
            {
    
    
                swap(nums[left],nums[right]);
                left++;
            }
            right++;
        }
    }
};

1.8 [Double pointer] [Hash table] The sum of two numbers

https://leetcode.cn/problems/two-sum/

(1) Double pointers, first sort the array, then use the double pointers to traverse the array from front to back, and finally find the corresponding subscripts in the original array for the two numbers found.
(2) Hash table. When traversing the array, find out whether the corresponding difference with the target is in the hash table. If yes, return the result directly. If not, add this element to the hash table and continue traversing. It should be noted here that the difference is target-nums[i], otherwise, if you encounter a negative number, you can only find another negative number.

//第一种方法---双指针
class Solution {
    
    
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    
    
        vector<int> nums2 = nums;
        sort(nums2.begin(),nums2.end());
        int n = nums2.size();
        int anum[2];
        vector<int> ans;
        for(int i=0,j=n-1;;)
        {
    
    
            if(nums2[i] + nums2[j] == target)
            {
    
    
                anum[0] = nums2[i];
                anum[1] = nums2[j];
                break;
            }
            else if(nums2[i] + nums2[j] > target) j--;
            else i++;
        }
        for(int i=0;i<n;i++)
        {
    
    
            if(nums[i]==anum[0])
            {
    
    
                ans.push_back(i);
                break;
            }
        }
        for(int j=n-1;j>=0;j--)
        {
    
    
            if(nums[j]==anum[1])
            {
    
    
                ans.push_back(j);
                break;
            }
        }
        sort(ans.begin(),ans.end());
        return ans;
    }
};

//第二种方法---哈希表
class Solution {
    
    
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    
    
        unordered_map<int,int> hash_table;
        vector<int> ans;
        for(int i=0;i<nums.size();i++)
        {
    
    
            int x = target - nums[i];
            if(hash_table.count(x))
            {
    
    
                ans.push_back(i);
                ans.push_back(hash_table[x]);
                return ans;
            }
            else hash_table[nums[i]] = i;
        }
        return ans;
    }
};

1.9 【Double Pointer】Effective Sudoku

https://leetcode.cn/problems/valid-sudoku/

For each row, each column, and each small nine-square grid, use a hash table to determine whether there are repeated elements, and pay attention to the subscript relationship of the nine elements of the small nine-square grid.

class Solution {
    
    
public:
    bool isValidSudoku(vector<vector<char>>& board) {
    
    
        bool flag = true;
        unordered_map<int,int> hash_table;
        //判断每行是否true
        for(int i=0;i<9;i++)
        {
    
    
            for(int j=0;j<9;j++)
            {
    
    
                if(board[i][j] != '.')
                {
    
    
                    int x = board[i][j] - '0';
                    if(hash_table.count(x)) return !flag;
                    else hash_table[x] = j;
                }
            }
            hash_table.clear();
        }
        //判断每列是否true
        for(int i=0;i<9;i++)
        {
    
    
            for(int j=0;j<9;j++)
            {
    
    
                if(board[j][i] != '.')
                {
    
    
                    int x = board[j][i] - '0';
                    if(hash_table.count(x)) return !flag;
                    else hash_table[x] = j;
                }
            }
            hash_table.clear();
        }
        //判断每个3*3是否true
        for(int k=0;k<9;k++)
        {
    
    
            int i_size = (k/3)*3;
            int j_size = (k%3)*3;
            for(int i=0;i<3;i++)
            {
    
    
                for(int j=0;j<3;j++)
                {
    
    
                    if(board[i+i_size][j+j_size] != '.')
                    {
    
    
                        int x = board[i+i_size][j+j_size] - '0';
                        if(hash_table.count(x)) return !flag;
                        else hash_table[x] = (i+1)*(j+1);
                    }
                }
            }
            hash_table.clear();
        }
        return flag;
    }
};

PS: Think about how the problem can be solved by traversing only once.

1.10 [Mathematics] Rotating an image

https://leetcode.cn/problems/rotate-image/

First flip the matrix up and down, and then flip it diagonally, mainly to understand the flip rule of 90 degrees

class Solution {
    
    
public:
    void rotate(vector<vector<int>>& matrix) {
    
    
        int n = matrix.size();
        //先上下翻转
        for(int i=0;i<n/2;i++)
        {
    
    
            vector<int> temp = matrix[i];
            matrix[i] = matrix[n-1-i];
            matrix[n-1-i] = temp;
        }
        //对角线翻转
        for(int i=0;i<n-1;i++)
        {
    
    
            for(int j=i+1;j<n;j++)
            {
    
    
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
    }
};

2 strings

2.1 [Double Pointer] Reverse String

https://leetcode.cn/problems/reverse-string/

Use double pointers to traverse the string array one after the other, and then exchange.

class Solution {
    
    
public:
    void reverseString(vector<char>& s) {
    
    
        int n = s.size();
        char temp;
        for(int i=0,j=n-1;i<j;i++,j--)
        {
    
    
            temp = s[i];
            s[i] = s[j];
            s[j] = temp;
        }
    }
};

2.2 [Mathematics] Reversal of integers

https://leetcode.cn/problems/reverse-integer/

This topic examines the range of int, and the range limit given in the topic is exactly the range of integers represented by int, so at the beginning, define a long-type traversal, and calculate the inverted integer after taking the remainder. If the integer After the type is converted to int, it is inconsistent with the original, indicating that the range of this integer exceeds int, otherwise it does not exceed.

class Solution {
    
    
public:
    int reverse(int x) {
    
    
        long ans = 0;
        while(x!=0)
        {
    
    
            int temp = x % 10;
            ans = ans*10 + temp;
            x /= 10;
        }
        if(int(ans)==ans) return ans;
        else return 0;
    }
};

2.3 [Hash Table] The first unique character in a string

https://leetcode.cn/problems/first-unique-character-in-a-string/

Using the hash table, if you encounter a repeated character, change the value of this character in the hash table to -1, otherwise store the index, and finally traverse the hash table to output the first index that is not -1, otherwise returns -1.

class Solution {
    
    
public:
    int firstUniqChar(string s) {
    
    
        unordered_map<char,int> hash_table;
        int n = s.size();
        for(int i=n-1;i>=0;i--)
        {
    
    
            char temp = s[i];
            if(hash_table.count(temp)) hash_table[temp] = -1;
            else hash_table[temp] = i;
        }
        int m = hash_table.size();
        for(auto x:hash_table)
        {
    
    
            if(x.second != -1) return x.second;
        }
        return -1;
    }
};

2.4 [Hash table] Valid anagrams

https://leetcode.cn/problems/valid-anagram/

Construct a hash table for the two strings, and finally compare whether the number of characters in each position is equal.

class Solution {
    
    
public:
    bool isAnagram(string s, string t) {
    
    
        int s_num[26]={
    
    0}, t_num[26]={
    
    0};
        for(int i=0;i<s.size();i++)
        {
    
    
            s_num[s[i]-'a']++;
        }
        for(int j=0;j<t.size();j++)
        {
    
    
            t_num[t[j]-'a']++;
        }
        for(int k=0;k<26;k++)
        {
    
    
            if(s_num[k]!=t_num[k]) return false;
        }
        return true;
    }
};

2.5 [Double Pointer] Verification Palindrome String

https://leetcode.cn/problems/valid-palindrome/

Use double pointers to solve the problem, but pay attention to judging a place when traversing, not only the value of 'a'-'A' is 32, but the value of 'P'-'0' is also 32, so when judging whether it is the same When uppercase and lowercase, add the judgment of whether both are letters.

class Solution {
    
    
public:
    bool isPalindrome(string s) {
    
    
        int n = s.size();
        if(n<=1) return true;
        for(int i=0,j=n-1;i<j;i++,j--)
        {
    
    
            while(!isalnum(s[i]) && i<j)
            {
    
    
                i++;
            }
            while(!isalnum(s[j]) && i<j)
            {
    
    
                j--;
            }
            if(s[i]!=s[j] && (s[i]<'A' || s[j]<'A' || abs(s[i]-s[j])!=32)) return false;
        }
        return true;
    }
};

2.6 [Violence] Convert string to integer (atoi)

https://leetcode.cn/problems/string-to-integer-atoi/

This question is disgusting, it makes me feel that I am always changing the code according to the needs.
First, when traversing the string, find out whether the number is positive or negative, and then output the complete number from the back to the found position. Here, I suggest that you read the question carefully, not to say that there are numbers after the output, but that you can find it immediately It is judged that the matching character is traversed backwards, and if there is no integer, 0 is directly output.
The following records the two pits I encountered
"20000000000000000000" and "0000000000012345678"
. The first one let me add a judgment to judge whether the number of digits of int exceeds the second one. The number starts to judge whether it exceeds the number of digits of int.

class Solution {
    
    
public:
    int myAtoi(string s) {
    
    
        int n = s.size();
        int i = 0;
        long ans = 0;
        int ans_size = 0;
        bool flag = true;
        while(i<n)
        {
    
    
            if(s[i]=='-')
            {
    
    
                flag = false;
                i++;
                break;
            }
            else if(s[i]=='+')
            {
    
    
                i++;
                break;
            }
            else if(s[i]!=' ')
            {
    
    
                break;
            }
            i++;
        }
        while(i<n)
        {
    
    
            if(s[i]=='0') i++;
            else break;
        }
        for(;i<n;i++)
        {
    
    
            if(s[i]<'0' || s[i]>'9') break;
            else
            {
    
    
                int x = s[i] - '0';
                ans = ans * 10 + x;
                ans_size++;
                if(ans_size > 10) break;
            }
        }
        if(!flag) ans = -ans;
        if(int(ans)==ans) return ans;
        else
        {
    
    
            if(flag) return pow(2,31)-1;
            else return -pow(2,31);
        }
    }
};

2.7 [Double Pointer] Find the subscript of the first matching item in the string

https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/

In fact, the best solution to this problem is kmp, but you can practice ordinary double-pointer search by yourself. What I implemented is a double-pointer solution without backtracking, that is, if there is a mismatch, the index of haystack is moved backwards. One, I will improve it later to see how kmp is implemented.

class Solution {
    
    
public:
    int strStr(string haystack, string needle) {
    
    
        int h_size = haystack.size();
        int n_size = needle.size();
        int n_index = 0;
        int ans = -1;
        for(int i=0;i<h_size;i++)
        {
    
    
            if(haystack[i] == needle[n_index])
            {
    
    
                ans = i;
                for(int j=i;j<h_size,n_index<n_size;j++,n_index++)
                {
    
    
                    if(haystack[j]!=needle[n_index])
                    {
    
    
                        n_index = 0;
                        ans = -1;
                        break;
                    }
                }
            }
        }
        return ans;
    }
};

2.8 [Violence] Appearance sequence

https://leetcode.cn/problems/count-and-say/

Violent solution, pay attention to observe the characteristics of the sequence, especially whether the last digit of the string is the same as the previous one, and also determine whether the number to be inserted is a single one, or inserted at the same time as the previous number, for example, the last end is "222" will insert "32", and the final ending is "223" will insert "2213".

class Solution {
    
    
public:
    string countAndSay(int n) {
    
    
        string ans = "11";
        int x_num = 1;
        if(n==1) return "1";
        if(n==2) return "11";
        for(int i=3;i<=n;i++)
        {
    
    
            string n_str;
            for(int j=0;j<ans.size();j++)
            {
    
    
                if(j==ans.size()-1)
                {
    
    
                    n_str.push_back(x_num + '0');
                    n_str.push_back(ans[j]);
                    x_num = 1;
                }
                else
                {
    
    
                    if(ans[j]==ans[j+1]) x_num++;
                    else
                    {
    
    
                        n_str.push_back(x_num + '0');
                        n_str.push_back(ans[j]);
                        x_num = 1;
                    }
                }
            }
            ans = n_str;
        }
        return ans;
    }
};

2.8 [Dictionary Tree] Longest Common Prefix

https://leetcode.cn/problems/longest-common-prefix/

Because here is to find out the longest common prefix, each string in strs is vertically compared and compared one by one. Once there is a vertical inconsistency, the loop will output ans immediately.

class Solution {
    
    
public:
    string longestCommonPrefix(vector<string>& strs) {
    
    
        string ans = "";
        for(int i=0;strs[0][i];i++)
        {
    
    
            for(int j=0;j<strs.size()-1;j++)
            {
    
    
                if(strs[j][i]!=strs[j+1][i]) return ans;
            }
            ans.push_back(strs[0][i]);
        }
        return ans;
    }
};

Guess you like

Origin blog.csdn.net/qq_44528283/article/details/130256344