Two pointers and variants Flashcards

(10 cards)

1
Q

Two sum: input array not sorted
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

Make a hashmap: number -> index it is present at

for each number in array check if difference = target - number is present, if yes it’s your answer
else add the number -> index in map

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Two sum II: input array is sorted

A

Use two pointers and run until left < right
sum = arr[left] + arr[right]
if sum == target: you found it
if sum > target: arr[right] is too big, right–
else arr[left] if too small, left++

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

3Sum:
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

Sort array, iterate over it, and reduce finding the other two in the result triplet to 2 sum problem, searching from index+1 to end of array

for(int index=0; index < nums.length; index++) {
if (index>0 && nums[index-1] == nums[index])
continue; //eliminate duplicate pairs
modifiedTwoSearch(nums, index, result);
}

modifiedTwoSearch(int[] nums, int index, List<List<Integer>> result) {
int left=index+1, right = nums.length-1;
int target = -1 * nums[index];
while(left<right) {
int sum = nums[left] + nums[right];
if (sum==target) {
result.add(index, left and right); left++; right--;
//eliminate duplicate pairs
while(left<right && nums[left]==nums[left-1]) left++;
while(left < right && nums[right]==nums[right+1]) right--;
} else if (sum > target) {
right--;
} else {
left++;
}
}
}</Integer>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

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

Note that you must do this in-place without making a copy of the array.

A

Two pointers: use index to traverse array and nextNonZeroIndex to track where next non-zero needs to be placed

If at index there is non zero:
1. swap it with what is at nextNonZeroIndex
2. increment nextNonZeroIndex

[0,1,0,3,12] -> [1,0,0,2,12] -> [1,2,0,0,12] -> [1,2,12,0,0]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Sort colors
Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.

We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.

You must solve this problem without using the library’s sort function.

A

Approach 1: count sort, which takes 2 O(n) loops

Approach 2: one O(n) loop with two pointers, p0 -> rightmost boundary for 0’s, p2 -> leftmost boundary for 2’s, and move them inward

p0 = 0, p2 = nums.length-1, index=0
while(index <= p2) {
if (nums[index]==0) {
swap(nums, index, p0); p0++; index++;
} else if (nums[index]==2) {
swap(nums, index, p2); p2–;
} else {
index++;
}
}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Trapping rain water - two pass solution
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.

Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Explanation: In this case, 6 units of rain water are being trapped.

A

Idea is to find the max height of any bar, including current one, to both left and right of current index.
Then the water that can be trapped at current index is = min(left_max,right_max)−height[i]

int[] maxLeft = new int[height.length];
int[] maxRight = new int[height.length];
maxLeft[0] = height[0];
maxRight[height.length-1] = height[height.length-1];

for(int index=height.length-2; index>=0; index–) {
maxRight[index] = Math.max(maxRight[index+1], height[index]);
}

int waterTrapped = 0;
for(int index=1; index<height.length-1; index++) {
maxLeft[index] = Math.max(height[index], maxLeft[index-1]);
waterTrapped += Math.min(maxLeft[index] , maxRight[index]) - height[index];
}

return waterTrapped;

Optimize this by reducing space needed for maxLeft array into O(1) by using one variable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Trapping rain water - one pass solution

A

Start at both ends with two pointers, and wherever the height is lower, advance the pointer inwards. Combine with Math.min(maxLeft[index] , maxRight[index]) condition to:
1. if heights[left] < heights[right]: waterTrapped += heights[left] - heights[index] for index left, advance the left pointer in
2. if heights[right] < heights[left]: waterTrapped += heights[right] - heights[index] for index right, advance right pointer in

    int left = 0, right=height.length-1;
    int waterTrapped = 0;
    int leftMax=0, rightMax=0;
    while(left < right) {
        if (height[left] < height[right]) {
            leftMax = Math.max(leftMax, height[left]);
            waterTrapped += leftMax - height[left];
            left++;
        } else {
            rightMax = Math.max(rightMax, height[right]);
            waterTrapped += rightMax - height[right];
            right--;
        }
    }
    return waterTrapped;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Longest Mountain in Array

You may recall that an array arr is a mountain array if and only if:

arr.length >= 3
There exists some index i (0-indexed) with 0 < i < arr.length - 1 such that:
arr[0] < arr[1] < … < arr[i - 1] < arr[i]
arr[i] > arr[i + 1] > … > arr[arr.length - 1]
Given an integer array arr, return the length of the longest subarray, which is a mountain. Return 0 if there is no mountain subarray.

Input: arr = [2,1,4,7,3,2,5]
Output: 5
Explanation: The largest mountain is [1,4,7,3,2] which has length 5.

A

Use two pointers and simulate the process of walking up and down a mountain

    if (arr.length < 3) return 0;
    int result=0, baseOfMountain = 0;
    boolean uphill = false, downhill = false;
    while(baseOfMountain < arr.length-1) {
        if (arr[baseOfMountain] >= arr[baseOfMountain+1]) {
            baseOfMountain++;
            continue;
        }
        int end = baseOfMountain;
        //we walk up and down a mountain starting at base and ending at end
        while(end+1 < arr.length && arr[end] < arr[end+1]) { //increasing
            end++;
            uphill = true;
        }
        while(end < arr.length-1 && arr[end] > arr[end+1]) {
            end++;
            downhill = true;
        }
        if (uphill && downhill)
            result = Math.max(end - baseOfMountain + 1, result);
        uphill = false;
        downhill = false;
        baseOfMountain = end;
    }
    return result;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Valid Palindrome

A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers.

Given a string s, return true if it is a palindrome, or false otherwise.

Input: s = “A man, a plan, a canal: Panama”
Output: true
Explanation: “amanaplanacanalpanama” is a palindrome.

A

Use two pointers, advance each as long as it is within bounds (left < right) and is not alphanumeric:

    int left=0, right = s.length()-1;
    while(left < right) {
        while(left < right && !Character.isLetterOrDigit(s.charAt(left)))
            left++;
        while(left < right && !Character.isLetterOrDigit(s.charAt(right)))
            right--;
        if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right)))
            return false;
        left++;
        right--;
    }
    return true;
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Valid Palindrome II

Given a string s, return true if the s can be palindrome after deleting at most one character from it.

Input: s = “abca”
Output: true
Explanation: You could delete the character ‘c’.

A

Idea: use two pointers, if characters are the same, advance them inwards. If not, try to move one inwards and do the same check recursively

    int left=0, right = s.length()-1;
    while(left < right) {
        if (s.charAt(left) != s.charAt(right)) {
            return (isPalindrome(s, left+1, right) || isPalindrome(s, left, right-1));
        }
        left++;
        right--;
    }
    return true;

isPalindrome is the usual O(N) check using two pointers.

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