LeetCode--双指针

题目一:二维数组中的查找

(2021/1/1)

在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。

给定 target = 20,返回 false

自己的方法一:暴力遍历:两重for循环,代码比较简单

自己的方法二:根据矩阵排序特点,设置一个行标记和列标记,从矩阵的左下角或者右上角出发进行查找

Java源代码

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        int row = matrix.length - 1;
        int col = 0;
        while (row >= 0 && col < matrix[0].length) {
            if (matrix[row][col] == target) {
                return true;
            } else if (matrix[row][col] > target) {
                row--;
            } else if (matrix[row][col] < target) {
                col++;
            }
        }
        return false;
    }
}

题目二:三数之和

(2021/1/4)链接:https://leetcode-cn.com/problems/3sum

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

方法一:我自己的思路就是三重循环,想不到更好的方法。

方法二:官方解答:排序+双指针

双指针法铺垫: 先将给定 nums 排序,复杂度为 O(NlogN)O(NlogN)。
双指针法思路: 固定 33 个指针中最左(最小)数字的指针 k,双指针 i,j 分设在数组索引 (k, len(nums))(k,len(nums)) 两端,通过双指针交替向中间移动,记录对于每个固定指针 k 的所有满足 nums[k] + nums[i] + nums[j] == 0 的 i,j 组合:
当 nums[k] > 0 时直接break跳出:因为 nums[j] >= nums[i] >= nums[k] > 0,即 33 个数字都大于 00 ,在此固定指针 k 之后不可能再找到结果了。
当 k > 0且nums[k] == nums[k - 1]时即跳过此元素nums[k]:因为已经将 nums[k - 1] 的所有组合加入到结果中,本次双指针搜索只会得到重复组合。
i,j 分设在数组索引 (k, len(nums))(k,len(nums)) 两端,当i < j时循环计算s = nums[k] + nums[i] + nums[j],并按照以下规则执行双指针移动:
当s < 0时,i += 1并跳过所有重复的nums[i];
当s > 0时,j -= 1并跳过所有重复的nums[j];
当s == 0时,记录组合[k, i, j]至res,执行i += 1和j -= 1并跳过所有重复的nums[i]和nums[j],防止记录到重复组合。
复杂度分析:
1)时间复杂度 O(N^2)O(N 
2 ):其中固定指针k循环复杂度 O(N)O(N),双指针 i,j 复杂度 O(N)O(N)。
空间复杂度 O(1)O(1):指针使用常数大小的额外空间。

Java源代码:

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> listresult = new ArrayList<>();
        Arrays.sort(nums);
        {
            for(int k = 0; k<nums.length-2;k++){
                if(nums[k]>0) return listresult;
                int i = k+1;
                int j = nums.length-1;
                if(k>0 &&nums[k]==nums[k-1]){
                    continue;
                }
                while(i<j){

                    if(nums[k]+nums[i]+nums[j] <0){
                        while(i<j &&nums[i] == nums[++i]);
                    }else if(nums[k]+nums[i]+nums[j]>0){
                        while(i<j && nums[j]== nums[--j]);
                    }
                    else{
                        List<Integer> templist = new ArrayList<>();
                        templist.add(nums[k]);
                        templist.add(nums[i]);
                        templist.add(nums[j]);
                        listresult.add(templist);
                        while(i<j &&nums[i] == nums[++i]);
                        while(i<j && nums[j]== nums[--j]);
                    }
                }
            }
        }
        return listresult;
    }
}

 

猜你喜欢

转载自blog.csdn.net/yezonghui/article/details/112055530
今日推荐