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
就行。
简单分析一下,什么时候会不出现?
首先,一种情况是haystack
比needle
长,这样子肯定不会存在。第二种情况就更好想了,就是单纯第二个字符串没有在第一个字符串中出现。
那如果出现了会有什么特征?也就是说第二个字符串在第一个字符串中能找到相同的部分,题目要求返回出现的第一个位置,那我们从前向后遍历第一个字符串就行了,如果某个元素和第二个字符串的首元素相同,那我们就挨着顺序对比下去,如果不相同,接着上次遍历到的位置继续遍历就行了,如果遍历到最后没有发现相同的部分,就返回-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
让我们一起进步吧!