编程导航算法村第三关 | 白银挑战

编程导航算法村第三关 | 白银挑战

原地移除所有数值等于 val 的元素

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

  • 使用快慢指针方法,slow执行的元素就是新数组
 public int removeElement(int[] nums, int val) {
        int slow = 0;
//            int fast=0;

        for (int fast = 0; fast < nums.length; fast++) {
            if (nums[fast] != val) {
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }

删除有序数组中的重复项

  • slow指向新数组,fast负责遍历
  • 如果fast能到达末尾,则直接将该元素赋值给slow数组
  • 判断fast与fast+1是否相等
  • 如果相等,fast++跳过所有的重复值,只保留第一个
public int removeDuplicates(int[] nums) {
        int slow = 0;
        for (int fast = 0; fast < nums.length; ) {
//            如果到达最后一个
            if (fast == nums.length - 1) {
//                if (nums[fast] != nums[fast - 1]) {
                nums[slow] = nums[fast];
                slow++;
                break;
//                }
            }

            if (nums[fast] != nums[fast + 1]) {

                nums[slow] = nums[fast];
                slow++;
                fast++;

            } else if (nums[fast] == nums[fast + 1]) {
                int temp = nums[fast];
                nums[slow] = temp;
                slow++;
                fast++;
                while (nums[fast] == temp) {
                    fast++;
                    if (fast >= nums.length) {
                        break;
                    }
                }
            }
        }
        return slow;
    }

  • 优化后
    • slow-1是新数组的最后一个元素
  public int removeDuplicates(int[] nums) {
        int slow = 1;
        for (int fast = 0; fast < nums.length; fast++) {
            if (nums[fast] != nums[slow - 1]) {
                nums[slow]=nums[fast];
                slow++;
            }
        }
        return slow;
}

元素奇偶移动专题

给你一个整数数组 nums,将 nums 中的的所有偶数元素移动到数组的前面,后跟所有奇数元素。
返回满足此条件的 任一数组 作为答案。
示例 1:
输入:nums = [3,1,2,4]
输出:[2,4,3,1]
解释:[4,2,3,1]、[2,4,1,3] 和 [4,2,1,3] 也会被视作正确答案。
示例 2:
输入:nums = [0]
输出:[0]
提示:
1 <= nums.length <= 5000
0 <= nums[i] <= 5000
Related Topics 数组 双指针 排序 👍 360 👎 0

public int[] sortArrayByParity(int[] nums) {
        int left = 0;
        int right = nums.length - 1;

        while (left < right) {
//            找到奇数
            if (nums[left] % 2 != 0) {
//                移动right直到找到偶数
                while (right > left) {
                    if (nums[right] % 2 == 0) {
//                        交换right与left的顺序
                        int temp = nums[left];
                        nums[left] = nums[right];
                        nums[right] = temp;
                        break;
                    }
                    right--;
                }
            }
            left++;
        }
        return nums;
    }

数组轮转问题

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
提示:
1 <= nums.length <= 10⁵
-2³¹ <= nums[i] <= 2³¹ - 1
0 <= k <= 10⁵
进阶:
尽可能想出更多的解决方案,至少有 三种 不同的方法可以解决这个问题。
你可以使用空间复杂度为 O(1) 的 原地 算法解决这个问题吗?
Related Topics 数组 数学 双指针 👍 1882 👎 0

以下这种解法错误,无法解决
[-1] 2的情况

 public void rotate(int[] nums, int k) {
        int[] temp = new int[k];
        
        int j = 0;

        for (int i = nums.length - k; i < nums.length; i++, j++) {
            temp[j] = nums[i];
        }
//    将剩余元素向后移动k位
        for (int i = nums.length - k - 1; i >= 0; i--) {
            nums[i + k] = nums[i];
        }

        for (int i = 0; i < k; i++) {
            nums[i] = temp[i];
        }

    }
  • 通过两轮翻转的方法
  • 例如
  • [1,2,3,4,5,6,7]
    3
  • 整体翻转变为:7 6 5 4 3 2 1
  • 翻转0到k-1 5 6 7 4 3 2 1
  • 翻转k到length-1 5 6 7 1 2 3 4
 public void rotate(int[] nums, int k) {
//        计算k在nums中的地址
        k %= nums.length;
//        整体翻转
        reverse(nums, 0, nums.length - 1);
//        翻转0——k-1
        reverse(nums,0, k-1);
//        翻转后一部分 k——nums.length - 1 
        reverse(nums,k, nums.length - 1);

    }

    public void reverse(int[] nums, int start, int end) {
        while (start < end) {
            int temp = nums[start];
            nums[start] = nums[end];
            nums[end] = temp;
            start++;
            end--;
        }
    }

汇总区间

给定一个 无重复元素 的 有序 整数数组 nums 。
返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于
nums 的数字 x 。
列表中的每个区间范围 [a,b] 应该按如下格式输出:
“a->b” ,如果 a != b
“a” ,如果 a == b
示例 1:
输入:nums = [0,1,2,4,5,7]
输出:[“0->2”,“4->5”,“7”]
解释:区间范围是:
[0,2] --> “0->2”
[4,5] --> “4->5”
[7,7] --> “7”
示例 2:
输入:nums = [0,2,3,4,6,8,9]
输出:[“0”,“2->4”,“6”,“8->9”]
解释:区间范围是:
[0,0] --> “0”
[2,4] --> “2->4”
[6,6] --> “6”
[8,9] --> “8->9”
提示:
0 <= nums.length <= 20
-2³¹ <= nums[i] <= 2³¹ - 1
nums 中的所有值都 互不相同
nums 按升序排列
Related Topics 数组 👍 268 👎 0

  • 将slow作为连续区间的起始位置,fast作为终点位置
public List<String> summaryRanges(int[] nums) {
        ArrayList<String> result = new ArrayList<>();
        int slow = 0;
//        [0,1,2,4,5,7]
        for (int fast = 0; fast < nums.length; fast++) {
            if (fast + 1 == nums.length || nums[fast] + 1 != nums[fast + 1]) {
                if (slow==fast){
                    result.add(nums[slow]+"");
                }else {
                    result.add(nums[slow]+"->" + nums[fast]);
                }

                slow = fast + 1;
            }
        }
        return result;
    }

字符串替换空格问题

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = “We are happy.”
输出:“We%20are%20happy.”
限制:
0 <= s 的长度 <= 10000
Related Topics 字符串 👍 512 👎 0

public String replaceSpace(String s) {
//        char[] chars = new char[];
        int cout = s.length();
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ' ') {
                cout+=2;
            }
        }
        char[] chars = new char[cout];
        for (int i = 0; i < s.length(); i++) {
//            if (s.charAt(i) == ' ') {
                chars[i] = s.charAt(i);

//            }
        }

        int slow = cout - 1;

        for (int fast = s.length()-1; fast >= 0; fast--) {
            if (chars[fast] != ' ') {
                chars[slow] = chars[fast];
                slow--;
            } else {
                chars[slow--] = '0';
                chars[slow--] = '2';
                chars[slow--] = '%';
            }

        }

        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < cout; i++) {
            stringBuilder.append(chars[i]);
        }

        return stringBuilder.toString();
//


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值