1.Array & String (with example problems)

Array & String

1. Tools: string functions in C++

These functions are frequently used in algorithm solution, for more details and functions, refer to this.

// Searches the string for the first occurrence of the str, returns index 
size_t find (const string& str, size_t pos = 0) const; 
// Returns a newly constructed string object with its value initialized to a copy of a substring starting at pos with length len. 
string substr (size_t pos = 0, size_t len = npos) const; 
// erase characters from pos with length len 
string &erase (size_t pos = 0, size_t len = npos); 
// Returns the length of the string, in terms of bytes
size_t length(); 

2. Problem Type:

2.1. Elements Occurrences

When a problem need us to count the occurrences of elements, we could use Hash Table(in C++, it could be unordered_map or map) to solve the problem. Key is the elements in the string, while the value is the occurrence of that. Sometimes, we are only required to determine whether elements is exist in string. In this kind of problem, we can also use bitset.

2.1.1. Examples:
  1. Determine if all characters of a string are unique.

  2. Given two strings, determine if they are permutations of each other

    1. 1 method: use hash table to determine whether count the occurrences in two strings are the same
    2. 2nd method: sort two strings, then compare if two strings are the same.
  3. Given a newspaper and message as two strings, check if the message can be composed using letters in the newspaper.

    1. use hash table to determine whether the letter occurrences in newspaper is greater than that in message.
    2. Time complex: O(n + m)
    3. Space complex: O( c ), which is the the number of letters
  4. Anagram: Write a method anagram(s,t) to decide if two strings are anagrams or not.

    1. To solve in O(n) time and O(1) extra space, we could hash the string s as dictionary. Then, iterate the string t and find out whether dictionary can be the anagram of t.

2.2. Using hash table to store the previous result

The main idea is similar to the dynamic programming, as hash takes O(1) time to attain the previous result.

2.2.1 Examples:
  1. Find a pair of two elements in an array, whose sum is a given target number.

    1. Let the pair as a + remains = target; We could use (key: a) as the elements in array, while (value: remain) is the a need to sum to target. If we find that the remain exist in the hash table, than return the result.
    2. Time complex: O(n)
  2. Get the length of the longest consecutive elements sequence in an array. For example, given [31, 6, 32, 1, 3, 2],the longest consecutive elements sequence is [1, 2, 3]. Return its length: 3.

    1. In this problem, we can using tuple<min, max> as value. For each elements n, we will find if n-1 or n+1 exist in hash table. If not, the key-value would be:{n: <n, n>}. If so, we can update previous tuple as new result.

2.3. Merge Array

2.3.1 Examples:

6. Merge Two Sorted Arrays

    vector<int> mergeSortedArray(vector<int> &A, vector<int> &B) {
        // write your code here
        vector<int> result;
        
        if(A.empty() ) 
            return B;
        
        if (B.empty() )
            return A;
            
        int i = 0, j = 0;
        
        int lenA = A.size(), lenB = B.size();
        while(i < lenA && j < lenB) {
            if(A[i] < B[j]) {
                result.push_back(A[i]);
                i++;
            } else {
                result.push_back(B[j]);
                j++;
            }
        }
        
        while(i < lenA ) {
            result.push_back(A[i]);
            i++;
        }
        
        while(j < lenB) {
            result.push_back(B[j]);
            j++;
        }
        
        return result;
        
    }

2.4. Mean/Median/#n in Arrays

When the problem gives two or more arrays, and want you to find out the median/mean of the arrays. Due to quantity of the numbers, it’s can be hard to sort the array. Thus, we will use two priority queue to maintain the data. Take mean as example, the smaller priority queue’s size is size/2, then the larger priority queue’s size is size - size/2. Note here, the smaller queue uses default less< T>, while the larger queue uses larger< T>. Finally, if the size is odd, then get the top of large queue, else take the top of the smaller queue.

Similar problem can also be get the first N large/small numbers in a data stream, all we need to do is change the size of priority_queue that need to maintain.

2.4.1 Examples:

64. Merge Sorted Array

    void mergeSortedArray(int A[], int m, int B[], int n) {
        // write your code here
        int i = m-1, j = n-1, k = m+n-1;
        while(k >=0){
            if(i < 0){
                A[k--] = B[j--];
            } else if (j < 0){
                A[k--] = A[i--];
            } else if (A[i] >= B[j]){
                A[k--] = A[i--];
            } else {
                A[k--] = B[j--];
            }
        }
    }

547. Intersection of Two Arrays

    vector<int> intersection(vector<int> &nums1, vector<int> &nums2) {
        // write your code here
        vector<int> res;
        
        int lenA = nums1.size(), lenB = nums2.size();
        int i =0, j = 0;
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());
        
        while(i < lenA && j < lenB) {
            if(nums1[i] < nums2[j])
                i++;
            if(nums1[i] > nums2[j])
                j++;
            if(nums1[i] == nums2[j]) {
                if(res.empty() || res[res.size() -1] < nums1[i])
                    res.push_back(nums1[i]);
                    

                i++;
                j++;
            }
        }
        
        return res;
    }

65. Median of two Sorted Arrays
Use two priority queues to maintain the median.

double findMedianSortedArrays(vector<int> &A, vector<int> &B) {
        // write your code here
        double result = 0.0;
        int m = A.size(), n = B.size();
        priority_queue<int> smaller, larger;
        
        int size = (m + n) / 2;
        
        A.insert(A.end(), B.begin(), B.end());
        if(A.size() == 1) {
            result += A[0];
            return result;
        }
        
        for(int i = 0; i < A.size(); i++) {
            
            if(i < size) {
                smaller.push(A[i]);
                continue;
            }
            int tmp = smaller.top();
            if(A[i] < tmp ) {
                smaller.pop();
                smaller.push(A[i]);
                tmp = -tmp;
                larger.push(tmp);
            } else {
                larger.push(-A[i]);
            }
        }

        int tmp = larger.top();
        if ( (m + n) % 2) {
            result -= tmp;
        } else {
            result += smaller.top();
            result -= tmp;
            result /= 2;
        }
        
        return result;
    }

2.4. Subarray: PrefixSum

Maintain an array that
PrefixSum[i] = A[0] + A[1] + … A[i - 1], PrefixSum[0] = 0,
which will take O(n) space and O(n) time.

What is the point to maintain such an array? When we need the sum from index i, to index j, then we have Sum(i~j) = PrefixSum[j + 1] - PrefixSum[i].

2.4.1 Examples:

41. Maximum Subarray

int maxSubArray(vector<int> &nums) {
        // write your code here
        vector<int> prefix_sum (nums.size() +1);
        
        for(int i = 0; i < nums.size(); i++) {
            prefix_sum[i +1] = prefix_sum[i] + nums[i];
        }
        
        int sum = INT_MIN;
        for(int i = 0; i < prefix_sum.size() -1; i++) {
            for(int j = i +1; j < prefix_sum.size(); j++) {
                int tmp = prefix_sum[j] - prefix_sum[i];
                if(tmp > sum ) {
                    sum = tmp;
                }
            }
        }
        
        return sum;
    }

Using sliding window method can be more efficient

    int maxSubArray(vector<int> &nums) {
        // write your code here
        if(nums.empty() )
            return 0;
            
        int sum = 0, maxSum = INT_MIN;
        for(auto num :  nums) {
            if (sum < 0)    
                sum = 0;
                
            sum += num;
            maxSum = max(sum, maxSum);
        }
        
        return maxSum;
    }

139. Subarray Sum Closest

    vector<int> subarraySumClosest(vector<int> &nums) {
        // write your code here
        vector<int> pre_sum (nums.size() +1);
        for(int i = 0; i < nums.size(); i++) {
            pre_sum[i +1] = pre_sum[i] + nums[i];
        }
        
        int diff = INT_MAX;
        vector<int> result{0, 0};
        for(int i = 0; i < pre_sum.size() -1; i++) {
            for(int j = i +1; j < pre_sum.size(); j++) {
                
                int tmp = abs(pre_sum[j] - pre_sum[i]);
                if(tmp == 0 )
                    return vector<int> {i, j -1};
                
                if(tmp < diff) {
                    diff = tmp;
                    result[0] = i;
                    result[1] = j -1;
                }
            }
        }
        
        return result;
    }

138. Subarray Sum
Using hash map to record the previous result.

vector<int> subarraySum(vector<int> &nums) {
        // write your code here
        if(nums.empty())
            return nums;
            
        vector<int> res;
        int sum = 0;
        
        unordered_map<int,int> hash;
        hash[0] = 0;
        
        for(int i = 0; i < nums.size(); i++){
            sum += i;
            if(hash.find(-sum) != hash.end()){
                res.push_back(hash[-sum] + 1);
                res.push_back(i);
                
            } 
            else 
            {
                hash[sum] = i;
            }
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值