Divide and Conquer(easy两道)(medium两道)

easy

169. Majority Element

Given an array of size n, find the majority element. The majority
element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element
always exist in the array.

Example 1:

Input: [3,2,3] Output: 3

Example 2:

Input: [2,2,1,1,1,2,2] Output: 2

O(n) time O(1) space fastest solution:

public class Solution {
    public int majorityElement(int[] num) {

        int major=num[0], count = 1;
        for(int i=1; i<num.length;i++){
            if(count==0){
                count++;
                major=num[i];
            }else if(major==num[i]){
                count++;
            }else count--;
            
        }
        return major;
    }
}

c++:

Hash Table:

The hash-table solution is very straightforward. We maintain a mapping
from each element to its number of appearances. While constructing the
mapping, we update the majority element based on the max number of
appearances we have seen. Notice that we do not need to construct the
full mapping when we see that an element has appeared more than n / 2
times.

The code is as follows, which should be self-explanatory.

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        unordered_map<int, int> counts; 
        int n = nums.size();
        for (int i = 0; i < n; i++)
            if (++counts[nums[i]] > n / 2)
                return nums[i];
    }
};

Sorting

Since the majority element appears more than n / 2 times, the n / 2-th
element in the sorted nums must be the majority element. This can be
proved intuitively. Note that the majority element will take more than
n / 2 positions in the sorted nums (cover more than half of nums). If
the first of it appears in the 0-th position, it will also appear in
the n / 2-th position to cover more than half of nums. It is similar
if the last of it appears in the n - 1-th position. These two cases
are that the contiguous chunk of the majority element is to the
leftmost and the rightmost in nums. For other cases (imagine the chunk
moves between the left and the right end), it must also appear in the
n / 2-th position.

The code is as follows, being very short if we use the system
nth_element (thanks for @qeatzy for pointing out such a nice
function).

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        nth_element(nums.begin(), nums.begin() + nums.size() / 2, nums.end());
        return nums[nums.size() / 2];
    } 
};

Randomization

This is a really nice idea and works pretty well (16ms running time on
the OJ, almost fastest among the C++ solutions). The proof is already
given in the suggested solutions.

The code is as follows, randomly pick an element and see if it is the
majority one.

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int n = nums.size();
        srand(unsigned(time(NULL)));
        while (true) {
            int idx = rand() % n;
            int candidate = nums[idx];
            int counts = 0; 
            for (int i = 0; i < n; i++)
                if (nums[i] == candidate)
                    counts++; 
            if (counts > n / 2) return candidate;
        }
    }
};

Divide and Conquer

This idea is very algorithmic. However, the implementation of it
requires some careful thought about the base cases of the recursion.
The base case is that when the array has only one element, then it is
the majority one. This solution takes 24ms.

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        return majority(nums, 0, nums.size() - 1);
    }
private:
    int majority(vector<int>& nums, int left, int right) {
        if (left == right) return nums[left];
        int mid = left + ((right - left) >> 1);
        int lm = majority(nums, left, mid);
        int rm = majority(nums, mid + 1, right);
        if (lm == rm) return lm;
        return count(nums.begin() + left, nums.begin() + right + 1, lm) > count(nums.begin() + left, nums.begin() + right + 1, rm) ? lm : rm;
    }
}; 

Moore Voting Algorithm

A brilliant and easy-to-implement algorithm! It also runs very fast,
about 20ms.

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int major, counts = 0, n = nums.size();
        for (int i = 0; i < n; i++) {
            if (!counts) {
                major = nums[i];
                counts = 1;
            }
            else counts += (nums[i] == major) ? 1 : -1;
        }
        return major;
    }
};

Bit Manipulation

Another nice idea! The key lies in how to count the number of 1’s on a
specific bit. Specifically, you need a mask with a 1 on the i-the bit
and 0 otherwise to get the i-th bit of each element in nums. The code
is as follows.

class Solution {
public:
    int majorityElement(vector<int>& nums) {
        int major = 0, n = nums.size();
        for (int i = 0, mask = 1; i < 32; i++, mask <<= 1) {
            int bitCounts = 0;
            for (int j = 0; j < n; j++) {
                if (nums[j] & mask) bitCounts++;
                if (bitCounts > n / 2) {
                    major |= mask;
                    break;
                }
            }
        } 
        return major;
    } 
};

53. Maximum Subarray

Given an integer array nums, find the contiguous subarray (containing
at least one number) which has the largest sum and return its sum.

Example:

Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has
the largest sum = 6.

Follow up:

If you have figured out the O(n) solution, try coding another solution
using the divide and conquer approach, which is more subtle.

DP solution & some thoughts:

Analysis of this problem:
Apparently, this is a optimization problem,which can be usually solved by DP. So when it comes to DP, the first thing for us to figure out is the format of the sub problem(or the state of each sub problem). The format of the sub problem can be helpful when we are trying to come up with the recursive relation.
At first, I think the sub problem should look like: maxSubArray(int A[], int i, int j), which means the maxSubArray for A[i: j]. In this way, our goal is to figure out what maxSubArray(A, 0, A.length - 1)
is. However, if we define the format of the sub problem in this way,
it’s hard to find the connection from the sub problem to the original problem(at least for me). In other words, I can’t find a way to divided the original problem into the sub problems and use the solutions of the sub problems to somehow create the solution of the original one.

So I change the format of the sub problem into something like:
maxSubArray(int A[], int i), which means the maxSubArray for A[0:i ]
which must has A[i] as the end element. Note that now the sub problem’s format is less flexible and less powerful than the previous
one because there’s a limitation that A[i] should be contained in that sequence and we have to keep track of each solution of the sub problem to update the global optimal value. However, now the connect between the sub problem & the original one becomes clearer:

maxSubArray(A, i) = maxSubArray(A, i - 1) > 0 ? maxSubArray(A, i - 1) : 0 + A[i];
And here’s the code

class Solution {
    public int maxSubArray(int[] A) {
            int n = A.length;
            int[] dp = new int[n];//dp[i] means the maximum subarray ending with A[i];
            dp[0] = A[0];
            int max = dp[0];

            for(int i = 1; i < n; i++){
                dp[i] = A[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);
                max = Math.max(max, dp[i]);
            }

            return max;
    }
}

medium

215. Kth Largest Element in an Array

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
在这里插入图片描述
Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.

https://leetcode.com/problems/kth-largest-element-in-an-array/discuss/60294/Solution-explained

240. Search a 2D Matrix II

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  1. Integers in each row are sorted in ascending from left to right.
  2. Integers in each column are sorted in ascending from top to bottom.
    在这里插入图片描述

My concise O(m+n) Java solution:

We start search the matrix from top right corner, initialize the current position to top right corner, if the target is greater than the value in current position, then the target can not be in entire row of current position because the row is sorted, if the target is less than the value in current position, then the target can not in the entire column because the column is sorted too. We can rule out one row or one column each time, so the time complexity is O(m+n).

public class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix == null || matrix.length < 1 || matrix[0].length <1) {
            return false;
        }
        int col = matrix[0].length-1;
        int row = 0;
        while(col >= 0 && row <= matrix.length-1) {
            if(target == matrix[row][col]) {
                return true;
            } else if(target < matrix[row][col]) {
                col--;
            } else if(target > matrix[row][col]) {
                row++;
            }
        }
        return false;
    }
}

猜你喜欢

转载自blog.csdn.net/xw_Summer/article/details/86612330
今日推荐