【算法】双指针

双指针法(快慢指针法)在数组和链表的操作中是非常常见的,很多考察数组、链表、字符串等操作的面试题,都使用双指针法。

在面试的时候被问到一个基础算法问题:怎样在一个链表中快速找到中间的那个值?

  因为没怎么刷过算法题,一问我就蒙了,我先是想c语言中的链表,但又想java里面其实并没有接触到这个概念了,只是底层的数据结构而已,我当成数组支支吾吾回答说先看链表长度然后取中间的,意外的是面试官说这也是一种解决方式,但肯定不是最优解。

  完事之后我去同学寝室时一说,他们一个室友就说是不是快慢指针问题,我开始不知道快慢指针,但是一下反应过来了,我们在遍历时使用两个索引,也就是两个指针,快索引走两步时慢索引走两步,这样快索引走完时慢索引刚好在中间。

  我靠!豁然开朗,这思路怎么我想不到,看来还是得刷刷算法题,下面就对我刷的一道经典快慢指针题做个笔记

力扣27.移除元素

力扣链接

  题目要求是从一个数组里原地移除指定元素:

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

  暴力解法就是双循环,不推荐

  然后就是双指针法,慢指针指新数组的尾部,快指针遇到和指定值不相等的元素就和慢指针交换值然后往后移,同时慢指针移一步;如果遇到相等的元素就快指针自己往后移一步,最后慢指针所指的就是新数组的长度:

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

力扣977.有序数组的平方

力扣链接

  给你一个按 递增顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 递增顺序 排序。

  这道题数组里面会有负数,但是数组按整体从小到大的顺序排列,简单的方法就是全部平方之后重新排序,所以优化的方式就是能不能平方的同时去往新的数组插数据。

  首先从头到尾去判断肯定不行,因为有正有负,负数平方之后会有些会大于正数,但是不管正负,平方最大的只可能在数组两头,所以我们有两个指针分别指向原数组头部和尾部,比较两者平方和,谁大就把该数插入到新数组最后的空位,插入之后指针后移或前移继续比较。

class Solution {
    public int[] sortedSquares(int[] nums) {
        int i = 0;
        int j = nums.length - 1,k = nums.length - 1;
        int[] a = new int[nums.length];
        while(i <= j){
            if(nums[i] * nums[i] > nums[j] * nums[j]){
                a[k] = nums[i] * nums[i];
                i++;
                k--;
            }
            else {
                a[k] = nums[j] * nums[j];
                j--;
                k--;
            }
        }
        return a;
    }
}

注意这里while(i <= j)我最开始写的i != j,这样会造成数组为偶数时少算最后一个元素。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值