数组-白银-双指针思想

1.删除数组内元素

  1.1原地删除数组内数值等于val的元素

     方法一:快慢双指针

思路:两指针的起点都是数组的首部,fast指针表示当前访问的元素,slow指针表示指针之前的元素都是有效元素,fast指针负责找到数值 != val 的元素 ,找到后slow,fast指针的元素互换,并且slow指针前进一步...

 public int removeElement(int[] arr,int val){
        //slow指针之前的代表有效元素
        int slow = 0;
        //fast指针负责遍历数组并找到 元素 != val 的元素
        for (int fast = 0;fast< arr.length;fast++){
            if (arr[fast] != val){
                arr[slow] = arr[fast];
                slow++;
            }
        }
        return slow;
    }

     方法二:对撞双指针

思路:两指针一个left,一个right,right指针找到数值 != val 的元素 与left指针找到数值 == val 的元素互换,当left<=right,left以及左侧就是删除了数值val元素的有效数组

 public  int removeElement(int[] arr,int val){
        int left = 0;
        int right = arr.length-1;
        for ( left = 0;left <= right;){
            if (arr[left]==val && arr[right] != val){
                int temp = arr[left];
                arr[left] = arr[right];
                arr[right] = temp;
            }
            if (arr[left] != val) left++;
            if (arr[right] == val) right --;
         }
        return left;
    }

  1.2删除有序数组的重复项

双指针思想:fast负责遍历数组,slow负责指向有效数组最后一个元素

fast指针的元素 !=  slow指针的元素,slow指针的元素发生变化......

slow赋初值为1,从数组索引为1开始考虑是否有效......

 public  int removeRepeat(int[] arr){
         int slow = 1;
         for (int fast = 0; fast<arr.length; fast++){
             if (arr[fast] != arr[slow-1]){
                 arr[slow] = arr[fast];
                 slow++;
             }
         }
         return slow;
    }

2.元素奇偶移动专题

题目:按奇偶排序数组,偶数元素后面是奇数元素

最简单的思路:开辟新数组空间,遍历要排序的数组两遍,分别挑选偶元素和奇元素在新数组排列,但是不推荐

推荐思路:采用双指针,核心是left寻找奇元素,right寻找偶元素,交换两指针元素

 public int[] sortArrayByParity(int[] arr){
        //left指针找奇元素,right指针找偶元素...SWAP
        int left = 0;
        int right = arr.length-1;
        for (left = 0;left <= right;){
            if (arr[left]%2 !=0 && arr[right]%2 == 0){
                int temp = arr[left];
                arr[left] = arr[right];
                arr[right] = temp;
            }
            if (arr[left]%2 ==0) left++;
            if (arr[right]%2 != 0) right--;
        }
        return arr;
    }

3.数组轮换问题

题意:输入nums=[1,2,3,4,5,6,7],k=3

           输出:[5,6,7,1,2,3,4]

思路:①先把原数组进行反转;②从k处分隔成两部分 [7,6,5],[4,3,2,1];③两部分分别进行反转

!!!    %= 运算符的使用  :取余后把值重新赋值

  /**
     * 向右轮转数组k个位置,掉用了reverse()
     * @param arr
     * @param key
     * @return
     */
    public void rotate(int[] arr,int key){
         key %= arr.length;
         //数组总体反转
         reverse(arr,0,arr.length-1);
         //反转后的数组[0,K-1],[K,arr.length-1]区间反转
         reverse(arr,0,key-1);
         reverse(arr,key,arr.length-1);
    }

    /**
     * 反转数组
     * @param arr
     * @return
     */
    public void reverse(int[] arr,int start ,int end){
       while (start < end){
           //temp 暂存区
           int temp = arr[start];
           arr[start] = arr[end];
           arr[end] = temp;
           start ++;
           end --;
       }
    }

4.数组的区间问题

题意:给定一个无重复的有序数组,返回恰好覆盖数组所有数字的最小有序区间范围列表

例如 nums=[0,1,2,4,5,7]

------->返回:["0->2","4->5","7"]

核心思想:使用双指针fast(遍历数组),slow(定位区间的开始),判断 fast +1 == arr.length

fast指针是否达到数组边界,arr[fast]+1 != arr[fast + 1] 判断是否是区间......

补充:ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制

  public List<String> numsRange(int[] arr){
        //存放返回的有效区间 字符串
        List<String> res = new ArrayList<>();
        //定义两个指针
        int fast = 0;
        int slow = 0;
        for (fast =0;fast<arr.length;fast++){
            //fast+1 到边界 或者 arr[fast+1] != arr[fast] + 1 ,即 [slow,fast]是一组有效区间
            if (fast+1 == arr.length || arr[fast+1] != arr[fast]+1){
                //将[slow,fast] 写入结果
                StringBuffer sb = new StringBuffer();
                sb.append(arr[slow]);
             if (slow != fast){
                 sb.append("->").append(arr[fast]);
             }
               res.add(sb.toString());
               // 将slow 更新为 下一个区间的起点
               slow = fast+1;
            }
        }
        return res;
    }

5.字符串替换空格问题

题意:把字符串的空格替换成 %20

思路一:申请一个新空间,存放替换空格为 %20 的字符串,遍历字符串,若字符串的元素为空格,则替换为 %20

  public String replaceSpace(String str){
        //申请新空间
        String res = "";
        for (int i =0;i<str.length();i++){
            //按索引顺序取出字符串的元素
            char c = str.charAt(i);
            if (c==' '){
                res += "%20" ;
            }else {
                res += c ;
            }
        }
        return res;
    }

思路二:先遍历字符串,得到字符串内的空格个数,定义新的字符串长度,该长度可以容纳替换空格为%20后的新串,定义两个指针,一个在旧字符串的尾部,一个在新字符串的尾部,旧字符串从后往前遍历,如果旧字符串的fast指针处元素不是空格,则新字符串slow处添加该元素,否则新字符串从slow处后往前插入 ‘0’,‘2’,‘%’,直到fast指针遍历到头部 并且 两指针相遇 ,替换完成......

   public String replaceSpace(StringBuffer str){
        if (str == null)
            return null;
        //获取旧字符串的长度
        int len = str.length();
        //定义空格的个数
        int numsOfBlank = 0;
        //遍历获取旧字符串的空格个数
        for (int i = 0; i < len; i++) {
            if (str.charAt(i)== ' ')
                numsOfBlank ++;
        }
        //定义新字符串的长度
        str.setLength((len+2*numsOfBlank));
        //定义两指针
        int fast = len -1;
        int slow = len+2*numsOfBlank -1;
        while (fast>=0 && slow>fast){
            char c = str.charAt(fast);
            if (c== ' '){
                fast --;
                str.setCharAt(slow--,'0');
                str.setCharAt(slow--,'2');
                str.setCharAt(slow--,'%');
            }else {
                str.setCharAt(slow,c);
                slow--;
                fast--;
            }
        }
        return str.toString();
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值