The sum of T15 three numbers of LeetCode brushing questions (medium)

The topic we are going to explain this time is LeeCode's medium topic, the sum of three numbers. Not much to say, the topic:

Insert picture description here
I believe that the first thought of many people is, violent solution, three-layer for loop, me too, but it is a big mistake! Because this question has a very important point, that is to remove the duplication!
Problem-solving ideas:
1: Sort the array first! The advantage of this is that it will be more intuitive and convenient when removing duplicates next!
2: Three pointers, the first pointer traverses the array, traversing from the position of index=0 to the position of index=nums.length-3, that is, from the beginning to the third last position
3: The other two one It is a head pointer, a tail pointer, head starts at i+1, and tail traverses from the end of the array.
4: The most important place is here. The rules for head and tail traversal:
(1) If sum<0 (the sum of the numbers pointed to by the three pointers), then the head needs to move to the right, because only in this way can it be guaranteed to be greater than In the same way, if sum>0, the tail needs to move to the left because the sum becomes smaller.
(2) If nums[i]>0, you can exit directly, because i+head+tail must be greater than 0
(3) Deduplication, because it has been sorted, then if i can meet the condition of sum=0, we need to continue to the back ++, and we need while to judge here, because the two are not necessarily connected together , Or it may be more than 2, then you can exclude multiple numbers that are connected together at once.
As shown in the figure:
Insert picture description here
Next, the code:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //定义返回的集合
        List<List<Integer>> lists=new ArrayList();
        Arrays.sort(nums);
        //遍历 从头一直遍历到倒数第三个
        for(int i=0;i<nums.length-2;i++){
            if(nums[i]>0) break; //如果此时已经大于0就说明后面全为整数再加也不会等于0
             int head=i+1;//定义头指针
             int tail=nums.length-1;//定义尾指针
             if(i>0&&nums[i]==nums[i-1]) continue; //如果连续相等的话就说明重复了,跳到下一个
             //当头指针和为指针相遇的时候结束循环
              while(head<tail){
                  int sum=nums[i]+nums[head]+nums[tail];
                  //满足条件时
                if(sum==0){
                    lists.add(Arrays.asList(nums[i],nums[head],nums[tail]));
                    while(head<tail&&nums[head]==nums[head+1]) head++; //头指针去重  这里要用while 不能用if 因为如果三个或者更多个相同的数字连在一起还是会重复,因为排了序,索性就让head或者tail继续移动到不后面不重复的地方 另外一个条件的作用就是防止head或者tail相遇 细节:这里head<tail需要先判断 [0,0,0] 这种情况,head会越界如果先,判断进行nums[head]==nums[head+1]的话就会数组下标越界
                    while(head<tail&&nums[tail]==nums[tail-1]) tail--; //尾指针去重
                    head++;
                    tail--;
                }
                //说明此时head指针需要往后移动,因为这样才能使sum变大
                else if(sum<0) {head++;}
                //说明此时tail指针需要往后移动,因为这样才能使sum变小
                else if(sum>0) {tail--;}
              }
        }
        return lists;
    }
}

Detailed description:
1: if(nums[i]>0) break; if it is already greater than 0 at this time, it means that all the following are integers and it will not be equal to 0. This has already been said
2: while(head<tail&&nums[head] ==nums[head+1]) head++; Why use while here? ? Because if you use if, the judgment is only made once. That is to say, if sum=0, the element after head and head is the same and de-duplicated, but it is not considered if there are more than two elements after head that are equal to him? ? That won’t work, so here we need to use while
3: (I won’t put the tail over for brevity!) while(head<tail&&nums[head]==nums[head+1]) head++; This place needs to be explained! ! ! ! ! ! ! ! ! Because the author got caught here! ! !
while(nums[head]==nums[head+1]&&head<tail) head++; Is there any difference between this method and the above method? ? At first glance it looks the same, you will find the location is different! But what is the impact? ? Hey, I made a mistake here! Next, listen to my analysis:
[0,0,0] In this case, the three are equal. In the judgment, the head will perform the operation of ++ and the tail will perform the operation of -, but because the length is 3, so Once the operation is completed, the positions of head and tail are exchanged. After the head passes ++ in the while loop, this will cause our head+1 to cross the boundary. If we use while(nums[head]==nums[head +1]&&head<tail) In this way, the position of head and head+1 will be judged whether they are equal, which will cause the array subscript out of bounds exception! ! So we have to judge head<tail first! ! !
Insert picture description here

This is the explanation of this topic. If it can help everyone, please pay attention to it. If you have any questions, please leave a message! thank you all!

Guess you like

Origin blog.csdn.net/Pzzzz_wwy/article/details/105719833