Analysis of Leetcode Problem Solving Ideas (38) 318-327

  1. Maximum word length product
    Given a string array words, find the maximum value of length(word[i]) * length(word[j]), and these two words do not contain common letters. You can think of each word as containing only lowercase letters. If there are no such two words, 0 is returned.

In order to facilitate comparison, you can take bit operations to store the bitfield of each word, and compare them with each other through bit operations.

class Solution {
    
    
public:
    int str2int(const string& s) {
    
    
        int res = 0;
        for (auto c : s)
            res |= 1 << (c - 'a');
        return res;
    }
    int maxProduct(vector<string>& words) {
    
    
        int N = words.size();
        vector<int> m(N, 0);
        for (int i = 0; i < N; ++i)
            m[i] = str2int(words[i]);
        int res = 0;
        for (int i = 0; i < N; ++i) {
    
    
            for (int j = 0; j < i; ++j) {
    
    
                if ((m[i] & m[j]) == 0 && words[i].size() * words[j].size() > res)
                    res = words[i].size() * words[j].size();
            }
        }
        return res;
    }
};

  1. Light bulb switch
    Initially, n light bulbs are turned off. In round 1, you turn on all the light bulbs. In the second round, you turn off every two light bulbs. In the third round, the switch is switched every three light bulbs (turn on if turned off, turn off if turned on). In the i round, the switch is switched every i bulbs. For the nth round, you only switch the last light bulb. Find out how many light bulbs are on after n rounds.

Only the perfect square number can satisfy the odd number of operations, the problem evolves to find the number of 1~n perfect square numbers, 1 * 1, 2 * 2,..., \sqrt{n} * \sqrt{n}, there is \sqrt {n} n

class Solution {
    
    
public:
    int bulbSwitch(int n) {
    
    
        return sqrt(n);        
    }
};
  1. Maximum number of stitching

Very classic greedy algorithm problem

class Solution {
    
    
public:
// 返回数组nums中,从idx,到nums.size()-len-1中最大数的索引。
int findMaxIndex(vector<int> &nums, int idx, int len){
    
    	
    int maxIdx = idx;
    for (int i=idx; i<nums.size()-len; i++){
    
    
        if (nums[i] > nums[maxIdx]) maxIdx = i;
    }
    return maxIdx;
}
typedef pair<int,int> P;
vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
    
    
    int n = nums1.size();
    int m = nums2.size();
    set<P> start;	// 存储所有可能的起点索引
    start.insert(pair<int,int>{
    
    0,0});	// 数组1初始起点为0,数组2初始起点为0。
    vector<int> ans;	//存储答案
    while(k){
    
    
        int maxNum = -1;// 第i位数初始值
        set<P> temp;	// 存储第i位数可以导致的所有可能的起点索引
        for(auto p:start){
    
    	// 考虑能够到达第i位的所有可能的起点索引
            int s1 = p.first;
            int s2 = p.second;
            int len1 = max(0, k-(m-s2+1));
            int maxIdx1 = findMaxIndex(nums1, s1, len1);	// 数组1此时能够取的最大数的索引
            int maxNum1 = maxIdx1 >= n ? -1 : nums1[maxIdx1];// 该索引对应的最大数
            if(maxNum1>=maxNum){
    
    
                if(maxNum1>maxNum) temp.clear();	// 如果当前起点索引获得的最大数比之前起点索引获得的最大值还要大,那么之前起点索引得到后续可能索引(temp)可以不用考虑。
                maxNum = maxNum1;
                temp.insert({
    
    maxIdx1+1, s2});	// 更新temp
            }
            int len2 = max(0, k-(n-s1+1));
            int maxIdx2 = findMaxIndex(nums2, s2, len2);
            int maxNum2 = maxIdx2 >= m ? -1 : nums2[maxIdx2];
            if(maxNum2>=maxNum){
    
    
                if(maxNum2>maxNum) temp.clear();
                maxNum = maxNum2;
                temp.insert({
    
    s1, maxIdx2+1});
            }
        }
        ans.push_back(maxNum);	//	确定第i位数
        start.swap(temp);	    //	下一位所有可能的起点索引
        k--;
    }
    return ans;
}
};
  1. Change Exchange
    Given coins of different denominations and a total amount. Write a function to calculate the minimum number of coins required to make up the total amount. If no coin combination can make up the total amount, return -1.

A typical greedy algorithm problem, each time the maximum denomination is selected, and then no return

class Solution {
    
    
public:
    void coinChange(vector<int>& coins, int amount, int c_index, int count, int& ans)
    {
    
    
        if (amount == 0)
        {
    
    
            ans = min(ans, count);
            return;
        }
        if (c_index == coins.size()) return;

        for (int k = amount / coins[c_index]; k >= 0 && k + count < ans; k--)
        {
    
    
            coinChange(coins, amount - k * coins[c_index], c_index + 1, count + k, ans);
        }
    }

    int coinChange(vector<int>& coins, int amount)
    {
    
    
        if (amount == 0) return 0;
        sort(coins.rbegin(), coins.rend());
        int ans = INT_MAX;
        coinChange(coins, amount, 0, 0, ans);
        return ans == INT_MAX ? -1 : ans;
    }
};
  1. Swing Sort 2
    Given an unordered array nums, rearrange it into the order of nums[0] <nums[1]> nums[2] <nums[3]...

Use the median method to split into two arrays, and then alternate splicing. In order to achieve O(1) space complexity, virtual addresses are directly mapped to the original array instead of creating a new array

class Solution {
    
    
public:
    void wiggleSort(vector<int>& nums) {
    
    
        int n = nums.size();

        // Find a median.
        auto midptr = nums.begin() + n / 2;
        nth_element(nums.begin(), midptr, nums.end());
        int mid = *midptr;

        // Index-rewiring.
        #define A(i) nums[(1+2*(i)) % (n|1)]

        // 3-way-partition-to-wiggly in O(n) time with O(1) space.
        int i = 0, j = 0, k = n - 1;
        while (j <= k) {
    
    
            if (A(j) > mid)
                swap(A(i++), A(j++));
            else if (A(j) < mid)
                swap(A(j), A(k--));
            else
                j++;
        }
    }
};


  1. Power of 3
    Given an integer, write a function to determine whether it is a power of 3.

Math questions, formulas

class Solution {
    
    
public:
    bool isPowerOfThree(int n) {
    
    
    if(n <= 0) return false;
    double a = log10(n) / log10(3) ;        //换底
    return  a == floor(a);         //判断换底后的log3n是否为整数,即n是否为3的倍数
    }
};


  1. The number of sections and
    given the nums an array of integers, and returns the number of intervals between [lower, Upper], comprising lower and upper.
    The interval sum S(i, j) means the sum of the elements from i to j in nums, including i and j (i ≤ j).

The method of interval sum has appeared several times before, which is to save the sum of each position to 0 and just subtract.

typedef long long LL;
class Solution {
    
    
public:
    
    vector<LL> data;
    vector<int> tr;
    
    // 查找小于等于x的第一个数的下标,找不到返回0
    int binary_search1(LL x) {
    
    
        
        int l = 0, r = data.size() - 1;
        while (l < r) {
    
    
            int mid = l + r + 1 >> 1;
            if (data[mid] <= x) l = mid;
            else r = mid - 1;
        }
        if (l == 0 && data[0] > x) return 0;
        else return l + 1;
    }
    
    // 查找小于x的第一个数的下标,找不到返回0
    int binary_search2(LL x) {
    
    
        int l = 0, r = data.size() - 1;
        while (l < r) {
    
    
            int mid = l + r + 1 >> 1;
            if (data[mid] < x) l = mid;
            else r = mid - 1;
        }
        if (l == 0 && data[0] >= x) return 0;
        else return l + 1;
    }
    
    int lowbit(int x) {
    
    
        return x & -x;
    }
    
    int find(int x) {
    
    
        int ans = 0;
        for (int i = x; i; i -= lowbit(i)) ans += tr[i];
        return ans;
    }
    
    void add(int x, int c) {
    
    
        int n = tr.size() - 1;
        for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;
    }
    
    int countRangeSum(vector<int>& nums, int lower, int upper) {
    
    
        int n = nums.size();
        LL sum = 0;
        vector<LL> s(n);
        for (int i = 0; i < n; i ++) {
    
    
            sum += nums[i];
            s[i] = sum;
        }
        data = s;
        data.push_back(0);
        sort(data.begin(), data.end());
        data.erase(unique(data.begin(), data.end()), data.end());
        tr = vector<int>(data.size() + 1);
        
//         for (int i = 0; i < data.size(); i ++) cout << data[i] << " ";
//         cout << endl;
        int ans = 0;
        int idx_zero = binary_search1(0);
        add(idx_zero, 1);
        for (auto x : s) {
    
    
            LL a = x - upper, b = x - lower;
            int idxa = binary_search2(a), idxb = binary_search1(b);
            int idxx = binary_search1(x);
            // cout << idxa << " " << idxb << " " << idxx << endl;
            if (idxb != 0) {
    
    
                if (idxa == 0) ans += find(idxb);
                else ans += find(idxb) - find(idxa);
            }
            add(idxx, 1);   
            // cout << ans << endl;
        }
        return ans;
    }
};




Guess you like

Origin blog.csdn.net/u013354486/article/details/108093537