Leecode练习 day01

1、合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
       int wNumber = nums1.length-1;
        int w1 = m-1;
        int w2 = n-1;

        while (w1>=0||w2>=0){
            if(w2 == -1) break;
            if(w1==-1|| nums2[w2]>nums1[w1]){
                nums1[wNumber] = nums2[w2];
                w2--;
            }else{
                nums1[wNumber] = nums1[w1];
                w1--;
            }
            wNumber--;
        }
    }
}

解题思路:

  • 逆向双指针:由于nums1是可以存下nums2的,所有使用逆向双指针比较nums1和nums2最后一位的大小,将较大的数放入nums1的末尾(因为这里nums1的末尾的空的,所以不存在覆盖的情况)每次存入后使nums1的尾指针减一
    在w2为-1时也就是nums2的数全部对比完成,则剩余的只剩nums1剩余的数必定是比nums2的数小的,所以直接退出
    在w1为-1时则nums1为空或全部对比完成,nums1对比完成则剩余nums2的数都是比nums1小的,所以直接存入nums1中

2、移除元素

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

示例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],也会被视作正确答案。

class Solution {
    public int removeElement(int[] nums, int val) {
        int t = 0;
        int w = nums.length-1;
        while(t<=w){
            if(nums[t]==val){
                nums[t] = nums[w];
                w--;
            }else{
                t++;
            }
        }
        return t;   
    }
}

解题思路:

双指针:使用一头一尾两个指针进行比较,在头部发现需要删除的数则和尾部交换且尾部指针减一。头部不为需要删除的数时则头部指针加一,在两个指针相遇时循环结束

3、删除有序数组中的重复项

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

示例 1:

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
class Solution {
    public int removeDuplicates(int[] nums) {
        int t = 1;
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] != nums[i - 1]) {
                nums[t] = nums[i];
                t++;
            }
        }
        return t;
    }
}

解题思路

快慢双指针,由于数组nums是按顺序排列的,相同的元素都在一起,所以可以使用快慢双指针。
快指针i遍历数组,如果nums[i] != nums[i-1]则前后不相等时,将nums[t] = nums[i],慢指针t++;如此循环当数组遍历结束时循环结束返回t值

4、删除有序数组中的重复项 II

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

示例 1:

输入:nums = [1,1,1,2,2,3]
输出:5, nums = [1,1,2,2,3]
解释:函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3。 不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,1,2,3,3]
输出:7, nums = [0,0,1,1,2,3,3]
解释:函数应返回新长度 length = 7, 并且原数组的前七个元素被修改为 0, 0, 1, 1, 2, 3, 3。不需要考虑数组中超出新长度后面的元素。

class Solution {
    public int removeDuplicates(int[] nums) {
    	//记录元素出现的次数
        int v=1;
        //头指针
        int t = 1;
        for(int i = 1; i < nums.length; i++){
        //当连续两个元素不一样时,将当前元素前移
            if(nums[i] != nums[i-1]){
                nums[t]=nums[i];
                t++;
                v = 1;
        //当v值小于2时,则当前元素出现次数小于2,则当前元素前移
            }else if(v<2){
                nums[t]=nums[i];
                t++;
                v++;
            }
        }
        return t;
    }
}

解题思路

快慢指针: 快满指针i、t都从下标为1的元素开始,如果sums[i] != sums[i-1] 相邻两个元素不一样,则当前元素出现次数重置为1,且将当前元素前移(如果i==t则说明前面元素都符合规则,则给自己赋值元素不变,如果前面出现超过2次重复元素时,则会t<i,则将i元素移至t位置),在sums[i] == sums[i-1] 且v<2时,则是当前元素出现次数小于2,将当前元素前移。

下面代码参考了leetcode官方代码、更加简便。

class Solution {
    public int removeDuplicates(int[] nums) {
        int t = 2;
        for(int i = 2; i < nums.length; i++){
           if( nums[i]!=nums[t-2]){
                nums[t] = nums[i];
                t++;
           }
        }
        return t;
    }
}

解题思路

快慢指针: 快慢指针t、i, 由于题目要求重复可以为2,则慢指针t不等于他前面第二位则重复值不会超过3([1,1,2] 2!=1 [1,1,1,] 1==1 ),所有当nums[i] != nums[i-2]时,重复元素则小于等于2,则将快指针i移至t,t++

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值