java 使用指针可以解答的算法 学习记录

 

常见双指针题解

两个大数相加

两个大整数相加的功能,其中大整数以字符串的形式表示。说明:

  1. 定义了两个大整数字符串 ab,以及一个 StringBuilder 用于存储相加的结果。
  2. albl 分别表示字符串 ab 的最高位的索引,初始化为字符串长度减1。
  3. c 用于记录进位,初始化为0。
  4. 使用 while 循环,循环条件是 al 大于等于0、bl 大于等于0 或者存在进位 c
  5. 在每次循环中,从字符串 ab 的当前位置获取对应的数字,并将它们与进位 c 相加,得到 t
  6. t 对10取模,得到当前位的结果,并将其插入到 StringBuilder 的最前面。
  7. t 除以10,得到进位 c
  8. 分别将 albl 减1,以处理下一位。
  9. 循环结束后,将 StringBuilder 中的结果转换为字符串,并打印输出。

这段代码的核心思想是模拟手工相加大整数的过程,从最低位开始逐位相加,处理进位,最终得到相加的结果。


@Test
public void test(){
    String a = "111111111111111111111111111111111111111111111111111111";
    String b = "11111111111111111111111111111111111111111111111111";
    StringBuilder stringBuilder = new StringBuilder(Math.max(a.length(),b.length()) +1);

    int al = a.length()-1;
    int bl = b.length()-1;
    int c = 0;
    while (al >=0 || bl >= 0 || c != 0) {
        int at = al>=0?a.charAt(al)-'0':0;
        int bt = bl>=0?b.charAt(bl)-'0':0;
        int t = at + bt + c;
        c = t/10;
        stringBuilder.append(t%10);
        al--;
        bl--;
    }
    System.out.println(stringBuilder.reverse().toString());
}

用指针方法求两个数组的交集

这段代码的作用是将数组a和数组b都进行排序,然后从后往前比较两个数组中的元素,如果相同则添加到结果集合中。如果不同,则将较大的那个数字所在数组的指针左移一位,直到其中一个指针小于0为止。


@Test
public void test(){
    int[] a = {5,2,3,1};
    int[] b= {2,5,1};

    Arrays.sort(a);
    Arrays.sort(b);
    int al = a.length-1;
    int bl = b.length-1;
    List<Integer> ll = new ArrayList<>();
    while (al >=0 || bl >= 0) {
        if (a[al] == b[bl]) {
            ll.add(a[al]);
            al--;
            bl--;
        }else if (a[al] >b [bl]) {
            al --;
        }else {
            bl --;
        }
    }
    System.out.println(ll);
}

删除一个元素使数组严格递增

给你一个下标从 0 开始的整数数组 nums ,如果 恰好 删除 一个 元素后,数组 严格递增 ,那么请你返回 true ,否则返回 false 。如果数组本身已经是严格递增的,请你也返回 true 。

数组 nums 是 严格递增 的定义为:对于任意下标的 1 <= i < nums.length 都满足 nums[i - 1] < nums[i] 。

示例 1:

输入:nums = [1,2,10,5,7]
输出:true
解释:从 nums 中删除下标 2 处的 10 ,得到 [1,2,5,7] 。
[1,2,5,7] 是严格递增的,所以返回 true 。
示例 2:

输入:nums = [2,3,1,2]
输出:false
解释:
[3,1,2] 是删除下标 0 处元素后得到的结果。
[2,1,2] 是删除下标 1 处元素后得到的结果。
[2,3,2] 是删除下标 2 处元素后得到的结果。
[2,3,1] 是删除下标 3 处元素后得到的结果。
没有任何结果数组是严格递增的,所以返回 false 。

https://leetcode.cn/problems/remove-one-element-to-make-the-array-strictly-increasing/description/


 public boolean canBeIncreasing(int[] nums) {
        int mark = 0;
        for(int i = 1;i<nums.length&& mark <= 1;i++) {
            // 证明当前数字比前一个大 就跳过,继续判断下一个数字
            if (nums[i] > nums[i-1]){
                continue;
            }

            // 否则需要变换元素位置
            mark ++;
            if (i-1>0 && nums[i] <= nums[i-2]) {
                nums[i] = nums[i-1];
            }
        }
        return mark <= 1;
    }
  • 第二个判断的逻辑: 判断当前元素是否还小于或等于其前前一个元素(即 nums[i] <= nums[i-2]),并且确保当前元素不是数组的第二个元素(即 i-1 > 0)。如果是这样,我们尝试通过将当前元素更新为其前一个元素来维持递增性(nums[i] = nums[i-1])。这一步意在处理类似 [1,5,3] 这种情况,由于 3 小于 5,但我们不能简单地把 5 降低到 2 或更小(因为这会违反递增规则),而是把 3 提升到 5,尽管这在实际操作中并不改变数组内容,但理念上是尝试通过修改 nums[i] 来保持整体递增。

最长连续序列 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。


示例 1:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。
示例 2:

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
 public int longestConsecutive(int[] nums) {
    if (nums.length == 0 || nums.length == 1) {
        return nums.length;
    }
    Arrays.sort(nums);
    int r = 1;
    int t = 1;
    for (int i = 1; i < nums.length; i++) {
        if (nums[i] - nums[i - 1] == 1) {
            r = Math.max(++t, r);
        } else if (nums[i] - nums[i - 1] != 0) {
            t = 1;
        }
    }
    return r;
}

else if (nums[i] - nums[i - 1] != 0) 代表不连续 就重置t

– 返回顶部 –