代码随想录-双指针

27. 移除元素https://leetcode-cn.com/problems/remove-element/

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

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

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

 1、暴力法  

每次检测到nums[i]==val  就从后往前移动一遍元素

 //暴力解法  遍历
    public int removeElement1(int[] nums,int val){
        int length=nums.length;
        for (int i= 0;i< length;++i){
            if(nums[i]==val){
                for (int j=i+1;j<length;++j){
                    nums[j-1]=nums[j];
                }
                i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
                length--;// 此时数组的大小-1
            }

        }
        return length;
    }

2、双指针

使用两个指针  left  right

left---------指向要插入的位置

right-------指向需要向前移动的元素 

        如果nums[right]!=val  就证明该元素需要向前移动

//双指针  快慢指针
    //left慢指针 right快指针
    public int removeElement(int[] nums,int val){
        int n=nums.length;
        int left=0;
        for (int right=0;right<n;++right){
            // 不等于目标值时  left才移动
            //-------这里要用if处理不相等时的情况
           
            if(nums[right]!=val){
                nums[left]=nums[right];
                left++;
            }
        }
        return left;
    }
// 时间复杂度:O(n)
// 空间复杂度:O(1)

344. 反转字符串icon-default.png?t=M1L8https://leetcode-cn.com/problems/reverse-string/

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

使用两个指针 left right

进行首尾对称调换即可 

//双指针
    //分别指向开头和结尾
    public void reverseString1(char[] s) {
        int n=s.length;
        //如果s的长度为偶数  循环结束时 right<left左边
        //如果s的长度为奇数  循环结束时 right=left
        for(int left=0,right=n-1;left<right;++left,--right){
            char tmp=s[left];
            s[left]=s[right];
            s[right]=tmp;
        }

    }

 剑指 Offer 05. 替换空格icon-default.png?t=M1L8https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/

 

如果想把这道题目做到极致,就不要只用额外的辅助空间了!

首先扩充数组到每个空格替换成"%20"之后的大小

然后从后向前替换空格,也就是双指针法,过程如下:

i指向新长度的末尾,j指向旧长度的末尾

//方法1-------变为char数组 扩充3倍  遍历即可
    public String replaceSpace1(String s) {
        int length=s.length();
        char[] array=new char[length*3];
        int size=0;
        for(int i=0;i<length;++i){
            char c=s.charAt(i);
            if(c==' '){
                array[size++] = '%';
                array[size++] = '2';
                array[size++] = '0';
            }else {
                array[size++] = c;
            }
        }
        String newStr = new String(array, 0, size);
        return newStr;
    }


    //方法2--------StringBuilder
    //使用一个新的对象,复制 str,复制的过程对其判断,是空格则替换,否则直接复制,类似于数组复制
    public static String replaceSpace2(StringBuffer str) {
        if (str == null) {
            return null;
        }
        //选用 StringBuilder 单线程使用,比较快,选不选都行
        StringBuilder sb = new StringBuilder();
        //使用 sb 逐个复制 str ,碰到空格则替换,否则直接复制
        for (int i = 0; i < str.length(); i++) {
            //str.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型
            //if (" ".equals(String.valueOf(str.charAt(i)))){
            if (str.charAt(i) == ' ') {
                sb.append("%20");
            } else {
                sb.append(str.charAt(i));
            }
        }
        return sb.toString();
    }

    //方法3-----------------双指针--从后向前移动
    //如果想把这道题目做到极致,就不要只用额外的辅助空间了!
    public String replaceSpace(String s){
        if(s==null||s.length()==0){
            return s;
        }
        //扩充空间为空格数量的2倍
        StringBuilder sb=new StringBuilder();
        for(int i=0;i<s.length();++i){
            if(s.charAt(i)==' '){
                sb.append("  ");
            }
        }
        //若是没有空格直接返回
        if(sb.length()==0){
            return s;
        }
        //有空格情况 定义两个指针
        int left=s.length()-1;//左指针:指向原始字符串最后一个位置
        s+=sb.toString();
        int right=s.length()-1;//右指针:指向扩展字符串的最后一个位置
        char[] chars=s.toCharArray();
        while (left>=0){
            if(chars[left]==' '){
                chars[right--]='0';
                chars[right--]='2';
                chars[right--]='%';
            }else {
                chars[right--]=chars[left];
            }
            left--;
        }
        return new String(chars);
    }

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值