Array(easy)七道题

1. Two Sum(easy)

Given an array of integers, return indices of the two numbers such
that they add up to a specific target.Given an array of integers,
return indices of the two numbers such that they add up to a specific
target.

You may assume that each input would have exactly one solution, and
you may not use the same element twice.

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].

Accepted Java O(n) Solution:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] result = new int[2];
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < numbers.length; i++) {
            if (map.containsKey(target - numbers[i])) {
                result[1] = i + 1;
                result[0] = map.get(target - numbers[i]);
                return result;
            }
            map.put(numbers[i], i + 1);
        }
        return result;
        
    }
}

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;
    }
}

121. Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a
given stock on day i.

If you were only permitted to complete at most one transaction (i.e.,
buy one and sell one share of the stock), design an algorithm to find
the maximum profit.

Note that you cannot sell a stock before you buy one.

Example 1:

Input: [7,1,5,3,6,4] Output: 5 Explanation: Buy on day 2 (price = 1)
and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.

Example 2:

Input: [7,6,4,3,1] Output: 0 Explanation: In this case, no transaction
is done, i.e. max profit = 0.

Kadane’s Algorithm - Since no one has mentioned about this so far ? (In case if interviewer twists the input):

The logic to solve this problem is same as “max subarray problem”
using Kadane’s Algorithm. Since no body has mentioned this so far, I
thought it’s a good thing for everybody to know.

All the straight forward solution should work, but if the interviewer
twists the question slightly by giving the difference array of prices,
Ex: for {1, 7, 4, 11}, if he gives {0, 6, -3, 7}, you might end up
being confused.

Here, the logic is to calculate the difference (maxCur += prices[i] -
prices[i-1]) of the original array, and find a contiguous subarray
giving maximum profit. If the difference falls below 0, reset it to
zero.

class Solution {
    public int maxProfit(int[] prices) {
            int maxCur = 0, maxSoFar = 0;
            for(int i = 1; i < prices.length; i++) {
                maxCur = Math.max(0, maxCur += prices[i] - prices[i-1]);
                maxSoFar = Math.max(maxCur, maxSoFar);
            }
            return maxSoFar;
    }
}

其中,
*maxCur = current maximum value

*maxSoFar = maximum value found so far

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;
    } 
};

283. Move Zeroes

Given an array nums, write a function to move all 0’s to the end of it
while maintaining the relative order of the non-zero elements.

Example:

Input: [0,1,0,3,12] Output: [1,3,12,0,0]

Note:

You must do this in-place without making a copy of the array. Minimize
the total number of operations.

Simple O(N) Java Solution Using Insert Index:

class Solution {
// Shift non-zero values as far forward as possible
// Fill remaining space with zeros

    public void moveZeroes(int[] nums) {
        if (nums == null || nums.length == 0) return;        

        int insertPos = 0;
        for (int num: nums) {
            if (num != 0) nums[insertPos++] = num;
        }        

        while (insertPos < nums.length) {
            nums[insertPos++] = 0;
        }
    }
}

448. Find All Numbers Disappeared in an Array

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array),
some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this
array.

Could you do it without extra space and in O(n) runtime? You may
assume the returned list does not count as extra space.

Example:

Input: [4,3,2,7,8,2,3,1]

Output: [5,6]

Java accepted simple solution:

The basic idea is that we iterate through the input array and mark
elements as negative using nums[nums[i] -1] = -nums[nums[i]-1]. In
this way all the numbers that we have seen will be marked as negative.
In the second iteration, if a value is not marked as negative, it
implies we have never seen that index before, so just add it to the
return list.

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
            List<Integer> ret = new ArrayList<Integer>();

            for(int i = 0; i < nums.length; i++) {
                int val = Math.abs(nums[i]) - 1;
                if(nums[val] > 0) {
                    nums[val] = -nums[val];
                }
            }

            for(int i = 0; i < nums.length; i++) {
                if(nums[i] > 0) {
                    ret.add(i+1);
                }
            }
            return ret;
    }
}

581. Shortest Unsorted Continuous Subarray

Given an integer array, you need to find one continuous subarray that
if you only sort this subarray in ascending order, then the whole
array will be sorted in ascending order, too.

You need to find the shortest such subarray and output its length.

Example 1: Input: [2, 6, 4, 8, 10, 9, 15] Output: 5 Explanation: You
need to sort [6, 4, 8, 10, 9] in ascending order to make the whole
array sorted in ascending order.

Note: Then length of the input array is in range [1, 10,000]. The
input array may contain duplicates, so ascending order here means <=.

Java O(n) Time O(1) Space:

I use the variables beg and end to keep track of minimum subarray
A[beg…end] which must be sorted for the entire array A to be sorted.
If end < beg < 0 at the end of the for loop, then the array is already
fully sorted.

class Solution {
    public int findUnsortedSubarray(int[] A) {
        int n = A.length, beg = -1, end = -2, min = A[n-1], max = A[0];
        for (int i=1;i<n;i++) {
          max = Math.max(max, A[i]);
          min = Math.min(min, A[n-1-i]);
          if (A[i] < max) end = i;
          if (A[n-1-i] > min) beg = n-1-i; 
        }
        return end - beg + 1;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值