Sword finger Offer II 007. Three numbers with 0 in the array

The js code is as follows:

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    if(nums.length<3){
        return [];
    }
    nums.sort((a,b)=>a-b);
    let result = [];
    for(let i=0;i<nums.length-2;i++){
        if(nums[i]>0){
            break;
        }
        if(i>0&&nums[i]==nums[i-1]){
            continue;
        }
        let start=i+1;
        let end=nums.length-1;
        while(start<end){
            let sum=nums[i]+nums[start]+nums[end];
            if(sum>0){
                end--;
                while(start<end && nums[end]==nums[end+1]){
                    end--;
                }
            }
            else if(sum<0){
                start++;
                while(start<end && nums[start-1]==nums[start]){
                    start++;
                }
            }
            else{
                result.push([nums[i],nums[start],nums[end]]);
                start++;
                end++;
                while(start<end&&nums[end]==nums[end+1]){
                    end--;
                }
                while(start<end&&nums[start-1]==nums[start]){
                    start++;
                }
            }
        }
    }
    return result;
};

At the beginning, the violent solution was used, but the time complexity was too high, resulting in timeout. Refer to other people's optimization ideas to get the above code

  • Idea: first judge the length of the given array. If it is less than 3, it will directly return the empty array. Since the output is in ascending order of the first number, the given array should be sorted in ascending order first. Specify a number as the standard, then set two pointers and look back. Start from the first element to the penultimate element as the standard, and then use the double pointer to find the other two numbers backward. The next thing to deal with is to avoid recording duplicate numbers. There are two kinds of repetition: 1) repetition as a standard number, and 2) repetition as a number pointed by a pointer under a standard number.
    The solution to case 1 is to judge whether the previous standard number is the same as the current standard number before searching for a new standard number. If it is the same, it will directly enter the next cycle, that is, if (I > 0 & & num [i] = = num [I-1]) {continue;} (because the previous standard number has found all the numbers with the following sum of 0 during double pointer search, there is no need to repeat the search for the same standard number).
    The solution to the second repeated case is to set a loop for judgment after each movement of two pointers. If the number pointed to by the previous pointer is the same, continue to move the pointer, that is, while (start < end & & num [End] = = num [end + 1]) {end --;} and while (start < end & & num [START-1] = = num [start]) {start + +;}.
    Finally, the data that satisfies the sum of three numbers and is 0 without repetition will be put into the array and returned.

Simplified part code:

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    if (nums.length < 3) return []

    nums.sort((a, b) => a - b)
    res = []
    for (let i = 0; i < nums.length - 2; i++) {
        // duplicate removal
        if (i > 0 && nums[i] == nums[i - 1]) continue

        const target = -nums[i]
        let left = i + 1, right = nums.length - 1
        while (left < right) {
            const sum = nums[left] + nums[right]
            if (sum == target) {
                res.push([nums[i], nums[left], nums[right]])
                /*
                The following code is equivalent to:
                while (left < right) {
                    // No matter the front and rear phases are not equal, the left should go forward
                    left++;
                    if (nums[left - 1] != nums[left]) break;
                }
                while (left < right) {
                    // No matter the front and back phases are not equal, right has to go back
                    right--;
                    if (nums[right + 1] != nums[right]) break;
                }
                */
                // duplicate removal
                while (left < right && nums[left] == nums[++left]);
                while (left < right && nums[right] == nums[--right]);
            } else if (sum < target) {
                left++
            } else {
                right--
            }
        }
    }
    return res
};

Tags: Javascript

Posted on Thu, 21 Oct 2021 11:31:51 -0400 by Norman Graham