Leetcode26-28,这几道简单有趣的算法题你都会吗?

26-删除排序数组中的重复项

题目要求:

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(1)额外空间的条件下完成。

示例1:

给定数组	nums = [1,1,2]
函数应该返回新的长度 2 ,并且原数组nums的前两个元素被修改为1,2
你不需要考虑数组中超出新长度后面的元素。

示例2:

给定数组	nums = [0,0,1,1,1,2,2,3,3,4]
函数应该返回新的长度 5,并且原数组nums的前五个元素被修改为 0,1,2,3,4
你不需要考虑数组中超出新长度后面的元素

来简单分析一下这道题,首先数组是排过序的,也就是说我们不需要用别的什么花里胡哨的算法,只需要对数组遍历一下就行。

然后需要在原地删除重复出现的元素,同时不能使用额外的数组空间,这个是什么意思呢?其实也就是说,你不能新建一个数组,然后在遍历的时候发现不同的数就给放入新数组。这样的话就不是对原数组进行修改了,而且还用了额外的新空间。

我们知道数组是引用数据类型,也就是说我们对传入的数组做任何改变都会直接移植到原数组,那么我们需要做的就是直接对原数组操作就行了。

同时还有最后一个特别重要的条件:你不需要考虑数组中超出新长度后面的元素。哎,这句话什么意思?其实这句话就向我们提供了一种思路:双指针。为什么会这么想?注意题目中要求是在原地删除元素,我们刚开始想的重点可能都是怎么把元素删除,当我们不需要考虑超出新长度后面的元素的时候,我们就可以直接对原数组修改就行了,不需要把数组中的元素删除。

实现思路

双指针,一个指针用来遍历原数组,找到不同的元素,另一个指针用来修改数组。遍历数组的指针是较快的指针,修改数组的指针是较慢的指针,当快的指针找到一个不重复的元素的时候,慢指针向前一位,然后修改该位的元素为快指针发现的不重复元素。

代码(Java):

public int removeDuplicates(int[] nums) {
    int i = 0;	//i 慢指针  j 快指针
    for (int j = 1; j< nums.length; j++) {
        if (nums[i] != nums[j]) {
            i++;
            nums[i] = nums[j];
        }
    }
    return i+1;
}

代码(Python):

def removeDuplicates(nums):
        nums[:] = sorted(set(nums))
        return len(nums)

嘿嘿,Python没有用和Java相同的思路写了,如果想实现相同思路,大家自己可以试着写一下。咱们来分析一下如上的代码。

因为Python有个数据类型叫集合,只要set()一下,列表中的元素就不相同了,同时因为集合具有无序的特性,就用sorted()给去重后的集合排个序。那有同志可能要说了,为什么不直接一行代码:

return len(sorted(set(nums)))搞定,还得切个整个集合的片?

因为leetcode有要求嘛,需要在原地删除元素,也就是说,对引用的数组做操作,而在leetcode的代码框里面是这样的:

class Solution(object):
    def removeDuplicates(self, nums):
        nums[:] = sorted(set(nums))
        return len(nums)

也就是说,这是类的一个方法,如果在类中你写一个nums变量,那它只是一个新变量,并不是方法传入的那个nums,因此最后返回的长度只是那个新变量的长度,而不是原数组的长度。

27-移除元素

题目要求:

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

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

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

示例1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

示例2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。

其实这道题跟上道题是十分类似的,上道题目是删除相同的元素,这道题是删除等于给定值的元素,实际上这道题比上一道更加简单了,如果上道题理解的同学可能已经对这道题有思路了。

实现思路

依然是双指针,遍历数组。题目要求移除等于指定值的元素,那我们就在遍历的时候如果碰到不等于指定值的元素,就用慢指针更改它位置上元素不久OK了。

代码(Java):

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

代码(Python):

class Solution(object):
    def removeElement(self, nums, val):
        i = 0
        for j in range(len(nums)):
            if nums[j] != val:
                nums[i] = nums[j]
                i += 1
        return i;

这次Python和Java实现方式相同了,大家可以对比看一下。

28-实现strStr()

题目要求:

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

题目很简短,给定两个字符串,如果第二个字符串在第一个字符串中出现,那么返回它第一次出现的位置,如果没有出现,返回-1就行。

简单分析一下,什么时候会不出现?

首先,一种情况是haystackneedle长,这样子肯定不会存在。第二种情况就更好想了,就是单纯第二个字符串没有在第一个字符串中出现。

那如果出现了会有什么特征?也就是说第二个字符串在第一个字符串中能找到相同的部分,题目要求返回出现的第一个位置,那我们从前向后遍历第一个字符串就行了,如果某个元素和第二个字符串的首元素相同,那我们就挨着顺序对比下去,如果不相同,接着上次遍历到的位置继续遍历就行了,如果遍历到最后没有发现相同的部分,就返回-1。实际上,我们不需要遍历到第一个字符串的最后一个位置,为什么?因为剩下的长度小于第二个字符串的时候肯定不会再出现了。

实现思路

首先确定两个字符串的长度,用一根指针遍历haystack字符串,然后直接判断haystack字符串从当前位置到needle长度的部分是否和needle是相同的,如果相同,直接返回当前位置,如果不相同,继续向后遍历。

代码(Java):

class Solution {
  public int strStr(String haystack, String needle) {
        int haylen = haystack.length();
        int neelen = needle.length();
        for (int i = 0; i < haylen - neelen + 1; i++) {
            if (haystack.substring(i, i + neelen).equals(needle)) {
                return i;
                }
        }
    return -1;
    }
}

代码(Python):

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        haylen = len(haystack)
        neelen = len(needle)
        for i in range(haylen-neelen +1):
            if haystack[i:i+neelen] == needle:
                return i
        return -1

好了,今天的题目分享就到这里,这都是题库里面非常简单的题目,注意消化分享,有不懂的地方多多留言交流哦~

你好,我是goldsunC

让我们一起进步吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳寜

“请作者吃颗糖!”

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值