Arrays Flashcards

1
Q

Two Sum

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

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

You can return the answer in any order.

A

It turns out we can do it in one-pass. While we iterate and inserting elements into the table, we also look back to check if current element’s complement already exists in the table. If it exists, we have found a solution and return immediately.

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            int compliment = target - nums[i]; // gets the number needed
            // check map
            if (map.containsKey(compliment)) {
                return new int[] {map.get(compliment), i};
            }
            // it wasn't in there, put it there
            map.put(nums[i], i);
        }
    throw new IllegalArgumentException("No two sum solution");
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Best Time to Buy and Sell Stock

You are given an array prices where prices[i] is the price of a given stock on the ith day.

You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.

Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.

A
class Solution {
    public int maxProfit(int[] prices) {
        int max = 0;
        int j = 1;
        for (int i = 0; j < prices.length ; j++) {
            if (prices[j] - prices[i] > max) {
                max = prices[j] - prices[i];
            }
            if (prices[i] > prices[j]) {
                i = j;
            }
        }
        return max;
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Contains Duplicate

Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct.

A

Use a Hash set to store the duplicates, check each time

class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set set = new HashSet<>();
        for (int i = 0; i < nums.length; ++i) {
            if (set.contains(nums[i])) {
                return true;
            }
            //isn't twice so add to set
            set.add(nums[i]);    
        }
        return false;
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Product of Array Except Self

Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].

The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

A

Given numbers [2, 3, 4, 5], regarding the third number 4, the product of array except 4 is 235 which consists of two parts: left 23 and right 5. The product is leftright. We can get lefts and rights:

Numbers: 2 3 4 5
Lefts: 2 23 234
Rights: 3
45 45 5
Let’s fill the empty with 1:

Numbers: 2 3 4 5
Lefts: 1 2 23 234
Rights: 3
45 45 5 1
We can calculate lefts and rights in 2 loops. The time complexity is O(n).

We store lefts in result array. If we allocate a new array for rights. The space complexity is O(n). To make it O(1), we just need to store it in a variable which is right in @lycjava3’s code.

Clear code with comments:

class Solution {
    public int[] productExceptSelf(int[] nums) {
        // treat them as values left and right then multiply them together
        int n = nums.length;
        int[] res = new int[n];
        // calculate lefts + store in res
        int left = 1; 
        for (int i = 0; i < n; ++i) {
            if (i > 0) {
                left = left * nums[i-1];
            }
            res[i] = left;
        }
        // calculate rights and the product in res (lefts)
        int right = 1;
        for (int i = n - 1; i >= 0; i--) {
            if (i < n - 1) {
                right = right * nums[i + 1];
            }
            res[i] *= right;
        }
        return res;
    }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

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.

A

Kadanes Algorithm

class Solution {
    public int maxSubArray(int[] nums) {
        // Initialize our variables using the first element.
        int currentSubarray = nums[0];
        int maxSubarray = nums[0];
        // Start with the 2nd element since we already used the first one.
        for (int i = 1; i < nums.length; i++) {
            int num = nums[i];
            // If current_subarray is negative, throw it away. Otherwise, keep adding to it.
            currentSubarray = Math.max(num, currentSubarray + num);
            maxSubarray = Math.max(maxSubarray, currentSubarray);
        }
    return maxSubarray;
} }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Max Subarray Product

Given an integer array nums, find a contiguous non-empty subarray within the array that has the largest product, and return the product.

It is guaranteed that the answer will fit in a 32-bit integer.

A subarray is a contiguous subsequence of the array.

A
class Solution {
    public int maxProduct(int[] nums) {
       if (nums.length == 0) {
            return 0;
        }
    int maxherepre = nums[0]; // pre-calc'd max
    int minherepre = nums[0]; // pre-calc'd min
    int maxsofar = nums[0]; // global max
    int maxhere, minhere; // local min and max

    for (int i = 1; i < nums.length; i++) {
        maxhere = Math.max(Math.max(maxherepre * nums[i], minherepre * nums[i]), nums[i]);  // local max -> previous max and min * nums[i] vs nums[i], can be min b/c negative * negative can make larger
        minhere = Math.min(Math.min(maxherepre * nums[i], minherepre * nums[i]), nums[i]); // local min -> previous max and min * nums[i] vs nums[i]
        maxsofar = Math.max(maxhere, maxsofar); // current global max
        maxherepre = maxhere; // previous max
        minherepre = minhere; // previous min (can become max quickly w/ another negative)
    }
    return maxsofar;
} }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Find Min of rotated array

Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:

[4,5,6,7,0,1,2] if it was rotated 4 times.
[0,1,2,4,5,6,7] if it was rotated 7 times.
Notice that rotating an array [a[0], a[1], a[2], …, a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], …, a[n-2]].

Given the sorted rotated array nums of unique elements, return the minimum element of this array.

A

Obvious is to just crawl the array or stream it, but you can use binary search to find the inflection point (not normal binary search) when you do that you get the smallest number!

public int findMin(int[] nums) {
        // easiest here is to just crawl array
        //return Arrays.stream(nums).min().getAsInt();
        // Optimal Solution
        if (nums.length == 1) {
            return nums[0];
        }
        // initializing left and right pointers.
        int left = 0;
        int right = nums.length - 1;
        // if the last element is greater than the first element then there is no rotation.
        // e.g. 1 < 2 < 3 < 4 < 5 < 7. Already sorted array.
        // Hence the smallest element is first element. A[0]
        if (nums[right] > nums[left]) {
            return nums[left];
        }
        // binary search (for midpoint cause its smallest)
        while (right >= left) {
            int mid = left + (right - left) / 2;
        if (nums[mid] > nums[mid + 1]) {
            return nums[mid + 1]; // number to the right is smaller (inflection) so its smallest
        }

        if (nums[mid - 1] > nums[mid]) {
            return nums[mid]; // number before mid is larger so mid must be smallest
        }
            if (nums[mid] > nums[0]) { // mid is larger than the first element, so the inflection is somewhere to right in array
                left = mid + 1;
            } else { // mid is greater than zero so we need to move right to the left since we are dealing with smaller #s
                right = mid - 1;
            }
        }
        return -1; // its not here
    }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

There is an integer array nums sorted in ascending order (with distinct values).

Prior to being passed to your function, nums is rotated at an unknown pivot index k (0 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], …, nums[n-1], nums[0], nums[1], …, nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be rotated at pivot index 3 and become [4,5,6,7,0,1,2].

Given the array nums after the rotation and an integer target, return the index of target if it is in nums, or -1 if it is not in nums.

A

public int search(int[] nums, int target) {
if (nums == null || nums.length == 0) {
return -1;
}

    /*.*/
    int left = 0, right = nums.length - 1;
    //when we use the condition "left <= right", we do not need to determine if nums[left] == target
    //in outside of loop, because the jumping condition is left > right, we will have the determination
    //condition if(target == nums[mid]) inside of loop
    while (left <= right) {
        //left bias
        int mid = left + (right - left) / 2;
        if (target == nums[mid]) {
            return mid;
        }
        //if left part is monotonically increasing, or the pivot point is on the right part
        if (nums[left] <= nums[mid]) {
            //must use "<=" at here since we need to make sure target is in the left part,
            //then safely drop the right part
            if (nums[left] <= target && target < nums[mid]) {
                right = mid - 1;
            }
            else {
                //right bias
                left = mid + 1;
            }
        }
        //if right part is monotonically increasing, or the pivot point is on the left part
        else {
            //must use "<=" at here since we need to make sure target is in the right part,
            //then safely drop the left part
            if (nums[mid] < target && target <= nums[right]) {
                left = mid + 1;
            }
            else {
                right = mid - 1;
            }
        }
    }
    return -1;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Three Sum:
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.

Notice that the solution set must not contain duplicate triplets.

A
public List> threeSum(int[] nums) {
        Arrays.sort(nums);
        List> output = new LinkedList();
    for (int i = 0; i < nums.length - 2; ++i) {
        if (i == 0 || (i > 0 && nums[i] != nums[i - 1])) {
            int low = i + 1;
            int high = nums.length - 1;
            int sum = 0 - nums[i];

            while (low < high) {
                if (nums[low] + nums[high] == sum) {
                    output.add(Arrays.asList(nums[i], nums[low], nums[high]));
                    while (low < high && nums[low] == nums[low+1]) low++;
                    while (low < high && nums[high] == nums[high-1]) high--;
                    low++;
                    high--;
                } else if (nums[low] + nums[high] > sum) {
                    high--;
                } else {
                    low++;
                }
            }
        }

}
     return output; }
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Container With Most Water

Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of the line i is at (i, ai) and (i, 0). Find two lines, which, together with the x-axis forms a container, such that the container contains the most water.

A
public int maxArea(int[] height) {
        // start on both sides, calc area, move smaller pointer
        // eventually they cross and we have correct value
        int max = Integer.MIN_VALUE;
        int i = 0;
        int j = height.length - 1;
    while(i < j) {
        int min = Math.min(height[i], height[j]);
        max = Math.max(max, min * (j - i));
        if (height[i] < height[j]) i++;
        else j--;
    }

    return max;
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly