首页 > 其他分享 >LeetCode 10 - 双指针

LeetCode 10 - 双指针

时间:2022-10-05 17:01:04浏览次数:80  
标签:10 right nums int ++ 指针 LeetCode left

11. 盛最多水的容器

方法:双指针

用两个指针指向「容器」的左右边界,每次移动数字较小那一侧的指针,直到两指针相遇。这样移动指针的正确性是可以保证的。

public int maxArea(int[] height) {
    int left = 0, right = height.length - 1;
    int maxArea = 0;
    while(left < right) {
        int area = 0;
        if(height[left] < height[right]) {
            area = height[left] * (right-left);
            left++;
        } else {
            area = height[right] * (right-left);
            right--;
        }
        if(area > maxArea) maxArea = area;
    }
    return maxArea;
}

15. 三数之和

给定一个数组,找出所有和为零的三元组。

方法:双指针

先把数组从小到大排序,然后在遍历数组时 for(int i = 0; i < nums.length; i++),对于每一个 i ,用两个指针分别指向 i+1 位置和最后一个元素的位置。目的是利用这两个指针找到和为 -nums[i] 的两个元素。

List<List<Integer>> threeSum(int[] nums) {
    int len = nums.length;
    List<List<Integer>> result = new ArrayList<>();
    if(len < 3) return result;

    Arrays.sort(nums); // O(nlogn)
    for(int i = 0; i < len; i++) {
        if(nums[i] > 0) break; // 注意是排好序的
        if(i > 0 && nums[i] == nums[i-1]) continue; // 去掉重复情况
        int targetSum = -nums[i];
        int left = i+1, right = len-1;
        while(left < right) {
            if(nums[left] + nums[right] == targetSum) {
                result.add(new ArrayList<>(Arrays.asList(nums[i], nums[left], nums[right])));
                // 移动两个指针,并保证移动后所指元素不和之前重复
                left++;
                right--;
                while(left < right && nums[left] == nums[left-1]) left++;
                while(left < right && nums[right] == nums[right+1]) right--;
            } else if(nums[left] + nums[right] < targetSum) {
                left++;
            } else {
                right--;
            }
        } // end of while
    } // end of for
    return result;
}

75. 颜色分类

数组中包含 0, 1, 2 三种数字,将它排序,使得所有 0 在最前面,接着是所有 1

方法一:单指针

维护一个指向最后一个 0 的指针,初始值为 0 ,遍历数组,将所有 0 与指针位置的元素交换;然后再遍历一遍,将所有的 1 与指针位置的元素交换(此时指针变成指向最后一个 1 的指针)。

void sortNums(int[] nums) {
    int ptr = 0;
    for(int i = 0; i < nums.length; i++) {
        if(nums[i] == 0) {
            nums[i] = nums[ptr];
            nums[ptr] = 0;
            ptr++;
        }
    }
    for(int i = ptr; i < nums.length; i++) {
        if(nums[i] == 1) {
            nums[i] = nums[ptr];
            nums[ptr] = 1;
            ptr++;
        }
    }
}

方法二:双指针

使用的指针和方法一类似,只是添加一个指向 1 序列结尾的指针 p1。遍历过程中,每发现一个 1 ,就将这个 1p1 位置交换,然后 p1++;每发现一个 0 ,如果当前 p0p1 前面,说明 p0 当前所指为 1 ,那么直接将遍历位置 i0p0 交换后, i 位置的 1 还需要与 p1 位置进行一次交换。然后 p0p1 需要同时后移一位。

void sortNums(int[] nums) {
    int p0 = 0, p1 = 0;
    for(int i = 0; i < nums.length; i++) {
        if(nums[i] == 1) {
            nums[i] = nums[p1];
            nums[p1] = 1;
            p1++;
        } else if (nums[i] == 0) {
            nums[i] = nums[p0];
            nums[p0] = 0;
            if(p0 < p1) {
                nums[i] = nums[p1];
                nums[p1] = 1;
            }
            p0++;
            p1++;
        }
    }
}

713. 乘积小于 K 的子数组

给定一个正整数组和一个目标值,求出满足 product < target 的子数组数量。

方法:双指针(滑动窗口)

right 指针枚举每一个元素,同时计算乘积;每轮枚举中,令 left = 0 ,不断向右移动左指针,直到乘积小于 target位于这个区间的子数组的乘积就小于 target,这个子数组的子数组个数为 right - left + 1

int subarrayProductLessThanK(int[] nums, int k) {
    if(k <= 1) return 0;
    int left = 0, product = 1;
    int result = 0;
    for(int right = 0; right < nums.length; right++) {
        product *= nums[right];
        // 找到以 right 结尾的乘积小于 k 的区间
        while(product >= k) {
            product /= nums[left];
            left++;
        }
        result += (right - left + 1);
    }
    return result;
}

202. 快乐数

编写一个算法来判断一个数 n 是不是快乐数。「快乐数」 定义为:

  • 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和
  • 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
  • 如果这个过程 结果为 1,那么这个数就是快乐数。

如果 n 是 快乐数 就返回 true ;不是,则返回 false 。

方法一:使用 HashSet 记录出现过的平方和

class Solution {
    public boolean isHappy(int n) {
        HashSet<Integer> set = new HashSet<>();
        int sum = getSumOfSquares(n);
        while (sum != 1) {
            if (set.contains(sum)) {
                return false;
            }
            set.add(sum);
            sum = getSumOfSquares(sum);
        }
        return true;
    }

    int getSumOfSquares(int n) {
        int sum = 0;
        while (n > 0) {
            int cur = n % 10;
            sum += cur * cur;
            n /= 10;
        }
        return sum;
    }
}

方法二:快慢指针

可以将每个平方和视为一个结点,初始状态下慢指针指向原始数 n,快指针指向该数的平方和 getSumOfSquares(n) ,然后慢指针每次移动一步:getSumOfSquares(slow) ,快指针每次移动两步:getSumOfSquares(getSumOfSquares(fast)) ,如果存在循环,两个指针最终会相遇。

public boolean isHappy(int n) {
    int slow = n;
    int fast = getSumOfSquares(n);
    while (fast != 1 && slow != fast) {
        slow = getSumOfSquares(slow);
        fast = getSumOfSquares(getSumOfSquares(fast));
    }
    return fast == 1;
}

标签:10,right,nums,int,++,指针,LeetCode,left
From: https://www.cnblogs.com/lzh1995/p/16755852.html

相关文章

  • LeetCode 07 - 二分查找
    注意几个点:区间的确定:一般写成闭区间[left=0,right=n-1]。循环条件的确定:因为使用闭区间,所以left==right在区间中是有意义的,所以循环条件为while(left<=right)......
  • 关闭sysMain服务解决win10系统硬盘占用率莫名增加到100%的卡顿问题
    最近电脑打游戏莫名会卡顿,甚至平常使用电脑都会感到卡顿感。打开任务管理器,看到硬盘占用率会突然涨到100%关闭superfetch服务后,卡顿问题得到解决。SysMain服务禁用方法:......
  • 2022.10.5 总结
    A初始时只有\(a_k=1\),有\(m\)次操作,每次交换\(a_u,a_v\)的值,问忽略多少次操作可以使最终\(a_i=1\).简单DP即可。code#include<algorithm>#include<cstdio>#in......
  • 2022.10.05考试总结
    2022.10.05考试总结得分:\(280/400\)总结:今天考试题目比较简单,第一,二题都是结论题,第三题在考场上因为没有考虑到有五十位导致挂了\(50\)分,第四题想到了正解,但是考试的时候......
  • 初学C语言笔记221005
    realloc调整动态内存开辟空间的大小​int*p1=(int*)malloc(10*sizeof(int));​if(p1==NULL){printf("%s",strerror(errno));}else{*p1=0x12345678;*......
  • LeetCode 04 - 栈
    1047.删除字符串中的所有相邻重复项给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在S上反复执行重复项删除操作,直到无法继续......
  • LeetCode 03 - 链表
    707.设计链表设计链表的实现,您可以选择使用单链表或双链表。在链表类中实现这些功能:get(index):获取链表中第index个节点的值。如果索引无效,则返回1。addAtHead(val......
  • 10.5 模拟赛
    \(\rmNOIP\)模拟赛\(\rmDate:10.5\)上次真是太变态了,这次就平和许多另外,不要在意accoders那丧心病狂的评测机速度了今天4道都是CF原题\(T1\)CF1252G一看上去居......
  • 1014 福尔摩斯的约会
     题目: 大侦探福尔摩斯接到一张奇怪的字条:我们约会吧!3485djDkxh4hhGE2984akDfkkkkggEdsbs&hgsfdkd&Hyscvnm 大侦探很快就明白了,字条上奇怪的乱码实际上就......
  • VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION(VGG) 阅读笔记(22
    VERYDEEPCONVOLUTIONALNETWORKSFORLARGE-SCALEIMAGERECOGNITION(VGG)阅读笔记(22.10.05)摘要:本文研究在大规模图像识别设置中卷积网络深度对其准确性的影响。主要贡献......