Google high frequency interview questions - smaller sum of three

preface

Hello, I'm brother Xiong.

Today, I'll bring you a high-frequency interview question related to array. This question has been tested as an interview question by Internet companies such as IBM, Google and Goldman Sachs, that is, the 259 question on the force buckle - the sum of smaller three numbers and the 918 question on the collar buckle - the sum of three numbers is less than.

This paper mainly introduces three methods to solve this problem, such as sorting + binary search and sorting + collision pointer, for your reference and hope to be helpful to you.

Smaller sum of three

Given a length of n An array of integers and a target value target,Look for conditions that enable

nums[i] + nums[j] + nums[k] < target Established triples i, j, k

Number (0) <= i < j < k < n). 

Examples and advanced

Problem solving ideas

It's easy to think of doing it through violent enumeration.

Solution 1: Violence Law

According to the meaning of the topic, traverse (three times) the whole array to find the solution that meets the conditions.

Show me the Code

C

int threeSumSmaller(int* nums, int numsSize, int target){
    int cnt = 0;
    for (int i = 0; i < numsSize - 2; ++i) {
        for (int j = i + 1; j < numsSize - 1; ++j) {
            for (int k = j + 1; k < numsSize; ++k) {
                if (nums[i] + nums[j] + nums[k] < target) {
                    cnt++;
                }
            }
        }
    }
    
    return cnt;
}

Complexity analysis

Time complexity: O(n^3), where n is the length of the array.

Space complexity: O(1), no additional storage space is opened up.

Operation results

Force buckle operation results

Due to the violence method, the time complexity is O(n^3), and the time complexity is too high, resulting in timeout on the force buckle (not on the collar buckle).

Solution 2: sorting + binary search

When you encounter search related problems, it is easy to think of the binary search method to solve them. Because this problem does not explain that the array is orderly, you need to sort the array first, and then binary search.

give an example

Take num = [- 2,0,1,3], target = 2 as an example, as shown in the figure below.

example

Since nums itself is ordered, there is no need to sort.

First fix i and j, and then find k satisfying the condition in (J, numsize - 1];

Determine search interval

Shorten the search interval according to the size relationship between num [mid] and target - num [i] - num [J];

Narrow the search

Then determine the logarithm of the triples that meet the conditions.

Determine the logarithm of the appropriate triples

The sorting + binary search method is adopted to complete the search process, as shown in the following figure:

Search process (sort + dichotomy)

Show me the Code

C

int comp(const void *a, const void *b) {
 return *(int *)a - *(int *)b;
}

int threeSumSmaller(int* nums, int numsSize, int target){
    if (nums == NULL || numsSize < 3) {
        return 0;
    }

    int cnt = 0;
    qsort(nums, numsSize, sizeof(int), comp);
    for (int i = 0; i < numsSize - 2; ++i) {
        for (int j = i + 1; j < numsSize - 1; ++j) {
            int sum = target - nums[i] - nums[j];
            int left = j + 1, right = numsSize - 1;
            while (left <= right) {
                int mid = left + (right - left) / 2;
                if (nums[mid] >= sum) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }

            cnt += (right - j);
        }
    }

    return cnt;
}

C++

int threeSumSmaller(vector<int>& nums, int target) {
    int cnt = 0;
    int size = nums.size();
    sort(nums.begin(), nums.end());
    for (int i = 0; i < size - 2; ++i) {
        for (int j = i + 1; j < size - 1; ++j) {
            int sum = target - nums[i] - nums[j];
            int left = j + 1, right = size - 1;
            while (left <= right) {
                int mid = left + (right - left) / 2;
                if (nums[mid] >= sum) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            cnt += (right - j);
        }
    }
    return cnt;
}

Java

int threeSumSmaller(int[] nums, int target) {
    int cnt = 0;
    Arrays.sort(nums);
    int size = nums.length;
    for (int i = 0; i < size - 2; ++i) {
        for (int j = i + 1; j < size - 1; ++j) {
            int sum = target - nums[i] - nums[j];
            int left = j + 1, right = size - 1;
            while (left <= right) {
                int mid = left + (right - left) / 2;
                if (nums[mid] >= sum) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
            }
            cnt += (right - j);
        }
    }
    return cnt;
}

Python3

def threeSumSmaller(nums, target):
    nums.sort()
    cnt, size = 0, len(nums)
    for i in range(len(nums) - 2):
        for j in range(i + 1, size - 1):
            sum = target - nums[i] - nums[j]
            left, right = j + 1, size - 1
            while left <= right:
                mid =  (right + left) // 2
                if nums[mid] >= sum:
                    right = mid - 1
                else:
                    left = mid + 1
            cnt += (right - j)
            
    return cnt

Golang

func threeSumSmaller(nums []int, target int) int {
 if len(nums) < 3 {
  return 0
 }

 cnt := 0
 sort.Ints(nums)
 for i := 0; i < len(nums) - 2; i++ {
        for j := i + 1; j < len(nums) - 1; j++ {
            sum := target - nums[i] - nums[j]
            left, right := j + 1, len(nums) - 1
            for left <= right {
                mid := left + (right - left) / 2
                if nums[mid] >= sum {
                    right = mid - 1
                } else {
                    left = mid + 1
                }
            }
            cnt = cnt + right - j
        }
        
 }
            
    return cnt
}

Complexity analysis

Time complexity: O(n^2lgn), where n is the length of the array.

Space complexity: O(1), no additional storage space is opened up.

Solution 3: sorting + collision pointer

In case of search related problems, if they are still orderly, in addition to binary search, the collision pointer method in double pointers can also be used to solve them.

give an example

Take num = [- 2,0,1,3], target = 2 as an example, as shown in the figure below.

Example

Compare the size relationship between num [left] + num [right] and target - num [i], so as to narrow the search range;

Search method

Determines the logarithm of the triples that satisfy the condition.

Determine results

The sorting + collision pointer method is used to complete the search process, as shown in the following figure:

Sorting + collision fingerpin search process

Show me the Code

C

int comp(const void *a, const void *b) {
 return *(int *)a - *(int *)b;
}

int threeSumSmaller(int* nums, int numsSize, int target){
    if (nums == NULL || numsSize < 3) {
        return 0;
    }

    int cnt = 0;
    qsort(nums, numsSize, sizeof(int), comp);
    for (int i = 0; i < numsSize - 2; i++) {
        int sum = target - nums[i];
        int left = i + 1, right = numsSize - 1;
        while (left < right) {
            if (nums[left] + nums[right] < sum) {
                cnt += (right - left);
                left++;
            } else {
                right--;
            }
        }
    }

    return cnt;
}

C++

int threeSumSmaller(vector<int>& nums, int target) {
    int cnt = 0;
    int size = nums.size();
    sort(nums.begin(), nums.end());
    for (int i = 0; i < size - 2; ++i) {
        int sum = target - nums[i];
        int left = i + 1, right = size - 1;
        while (left < right) {
            if (nums[left] + nums[right] < sum) {
                cnt += (right - left);
                left++;
            } else {
                right--;
            }
        }
    }

    return cnt;
}

Java

int threeSumSmaller(int[] nums, int target) {
    int cnt = 0;
    Arrays.sort(nums);
    int size = nums.length;
    for (int i = 0; i < size - 2; ++i) {
        int sum = target - nums[i];
        int left = i + 1, right = size - 1;
        while (left < right) {
            if (nums[left] + nums[right] < sum) {
                cnt += (right - left);
                left++;
            } else {
                right--;
            }
        }
    }

    return cnt;
}

Python3

def threeSumSmaller(nums, target):
    nums.sort()
    cnt, size = 0, len(nums)
    for i in range(len(nums) - 2):
        sum = target - nums[i]
        left, right = i + 1, size - 1;
        while left < right:
            if nums[left] + nums[right] < sum:
                cnt += (right - left)
                left += 1
            else:
                right -= 1

            
    return cnt

Golang

func threeSumSmaller(nums []int, target int) int {
 if len(nums) < 3 {
  return 0
 }

 cnt := 0
 sort.Ints(nums)
 for i := 0; i < len(nums) - 2; i++ {
        sum := target - nums[i]
        left, right := i + 1, len(nums) - 1
        for left < right {
            if nums[left] + nums[right] < sum {
                cnt += (right - left)
                left += 1
            } else {
                right -= 1
            }
        }
 }
            
    return cnt
}

Complexity analysis

Time complexity: O(n^2), where n is the length of the array.

Space complexity: O(1), no additional storage space is opened up.

Posted by aleigh on Mon, 29 Nov 2021 17:48:36 -0800