2021.7.18(双指针问题)

今天刷的还是关于双指针这一类型的题目,通过做题也可以发现有些题目可以使用相同的思想。

移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素

 思路:其实这道题想了很久,Leecode上面已经给出了该例题。

如果我们不使用额外的数组,只是在原数组上进行操作呢?

此时,我们就可以采用快慢指针的思想:初始化一个快指针 fast 和一个慢指针 slow,fast 每次移动一步,而 slow 只当 fast 指向的值不等于 val 时才移动一步。

 该题就是这种思路,定义快慢指针slow和fast,遍历数组元素,如果nums[fast]!=val,将当前nums[slow]=nums[right],slow++;最后放回数组元素长度,当时脑子比较混乱,逻辑一时理不太清。

class Solution {
    public int removeElement(int[] nums, int val) {
        int len=nums.length; 
        int slow=0;
        for(int fast=0;fast<len;fast++)
        {
            if(nums[fast]!=val){
                nums[slow]=nums[fast];
                slow++;
            }
        }
        return  slow;    
    }
}

第二题:移动0


给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

示例:

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:

必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。

思路:该题也可以使用快慢指针思路,将0都移除掉,然后再让slow后面的索引补0就可以了。

class Solution {
    public void moveZeroes(int[] nums) {
        int slow=0;
        int  len=nums.length;
        for(int  fast=0;fast<len;fast++){
            if(nums[fast]!=0){
                nums[slow]=nums[fast];
                slow++;
            }    
        }
        for(;slow<len;slow++){
            nums[slow]=0;
        }      
    }
}

第三题:

给定一个已按照 升序排列  的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

 
示例 1:

输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
示例 2:

输入:numbers = [2,3,4], target = 6
输出:[1,3]
示例 3:

输入:numbers = [-1,0], target = -1
输出:[1,2]

思路:注意数组升序排列,所以双指针分别指向数组开头和结尾,定义一个数组存放答案,

class Solution {
    public int[] twoSum(int[] numbers, int target) {
        int []result=new int[2];
        if(numbers.length<2)
        {
            return null;
        }
        int left=0;
        int right=numbers.length-1;
        while(left<=right){
            if(numbers[left]+numbers[right]==target)
            {
                result[0]=left+1;
                result[1]=right+1;
                break;
            }
            else if(numbers[left]+numbers[right]<target)
            {
                left++;//如果大于target,left右移
            }
            else{
                right--;//如果大于target,right左移
            }
        }
return result;
    }
}

在做题时,经常会用到一些函数。

math类中的一些方法

  • Math.sqrt() : 计算平方根
  • Math.cbrt() : 计算立方根
  • Math.pow(a, b) : 计算a的b次方
  • Math.max( , ) : 计算最大值
  • Math.min( , ) : 计算最小值
  • Math.abs() : 取绝对值
  • Math.ceil(): 天花板的意思,就是逢余进一
  • Math.floor() : 地板的意思,就是逢余舍一
  • Math.rint(): 四舍五入,返回double值。注意.5的时候会取偶数
  • Math.round(): 四舍五入,float时返回int值,double时返回long值

给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

输入:[1,8,6,2,5,4,8,3,7]
输出:49 
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例 2:

输入:height = [1,1]
输出:1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/container-with-most-water
 

public class Solution {
    public int maxArea(int[] height) {
        int l = 0, r = height.length - 1;
        int ans = 0;
        while (l < r) {
            int area = Math.min(height[l], height[r]) * (r - l);
            ans = Math.max(ans, area);
            if (height[l] <= height[r]) {
                ++l;
            }
            else {
                --r;
            }
        }
        return ans;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值