删除有序数组中的重复项
1.问题描述
2.问题分析
2.1 数组元素移动法
因为题目所给数组是有序的,并且在删除元素期间是不可以使用在数组之外的空间。所以第一思路想到的就是遍历数组,如果发现有重复的元素,那么就让后面的元素来前移代替这个重复的元素。然后将数组长度-1。直到遍历完成。
2.1.1 实现代码
/**
前提:数组有序、没有额外空间、在原数组上修改
思路:示例:0 0 1 1 2 3
1)从index=0开始遍历,判断nums[index]和nums[index+1]是否相同,若是相同,则2),若是不同,则3)
2)从下标为index+1包含index+1的位置开始,后面的元素向前挪动一位,然后数组长度-1
3)index累加,执行【判断逻辑 1)】==>直到index的位置等于当前数组长度-1。
例子:
0 0 1 1 2 3
1)0 1 1 2 3 3 因为发现重复元素,所以数据从第1位开始向前挪动,并且此时数组长度-1.更新为5.原本是6的
2)index继续累加。发现1重复了。所以新的数组是 0 1 2 3 3 3,此时数组长度继续-1.更新为4,原本是5
3)index继续累加到长度-1的位置。发现没有重复元素。遍历完成。最后的结果是前4个元素。
0 1 2 3
*/
class Solution {
public int removeDuplicates(int[] nums) {
int len = nums.length;
for(int i=0;i<len-1;i++){
if(nums[i]==nums[i+1]){
changeArr(i+1,len-2,nums);
len--;
}
}
return len;
}
/**
@param1 int start:开始向前挪动元素的开始位置
@param2 int end:结束向前挪动元素的位置
@param3 int[]nums :操作的数组
// @retrun int[] nums :返回操作后的数组
*/
public void changeArr(int start,int end,int[] nums){
for(int i=start;i<=end;i++){
nums[i] = nums[i+1];
}
}
}
public class MainClass {
public static int[] stringToIntegerArray(String input) {
input = input.trim();
input = input.substring(1, input.length() - 1);
if (input.length() == 0) {
return new int[0];
}
String[] parts = input.split(",");
int[] output = new int[parts.length];
for(int index = 0; index < parts.length; index++) {
String part = parts[index].trim();
output[index] = Integer.parseInt(part);
}
return output;
}
public static String integerArrayToString(int[] nums, int length) {
if (length == 0) {
return "[]";
}
String result = "";
for(int index = 0; index < length; index++) {
int number = nums[index];
result += Integer.toString(number) + ", ";
}
return "[" + result.substring(0, result.length() - 2) + "]";
}
public static String integerArrayToString(int[] nums) {
return integerArrayToString(nums, nums.length);
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = in.readLine()) != null) {
int[] nums = stringToIntegerArray(line);
int ret = new Solution().removeDuplicates(nums);
String out = integerArrayToString(nums, ret);
System.out.print(out);
}
}
}
2.1.3 算法分析
时间复杂度:因为每次发现重复元素都要遍历移动数据。所以时间复杂度O(n^2)
空间复杂度:没有占用额外空间
2.2 双指针取数法
大家都看过西游记,我这里类比唐僧没经过一个国家要通关文牒的例子。因为数据是有序的,所以我们把数据分类。每一个类别就是一个国家。那么这里的数据就是通关文牒。唐僧一直向前走,直到发现和上一个不同的国家才会去要通关文牒。那么这里也是同样的道理。
我们使用两个指针。指针1和指针2. 指针1指的是数组中不重复元素的位置,指针2的作用是遍历所有元素。
举例:
所给数组:0 1 1 2 2 2 4 6 6
指针1开始赋值=0
指针2同样也是0
1)指针2开始遍历,直到发现和自己值不一样的数据,也就是1.此时指针1++,并赋值为指针2发现的不同的数据
2)指针2继续遍历,发现了元素2. 指针1继续++,然后赋值为2
3)指针2继续遍历,发现4,然后指针1++,赋值为4
4)指针2继续遍历,发现6,然后指针1++,赋值为6
5)指针2越界,遍历结束
最后的结果是:
0 1 2 4 6
2.2.1 实现代码
class Solution {
public int removeDuplicates(int[] nums) {
int p1 = 0;
int p2 = 0;
for(;p2<nums.length-1;p2++){
if(nums[p2]!=nums[p2+1]){
nums[++p1] = nums[p2+1];
}
}
return p1+1;
}
}
2.2.2 算法分析
时间复杂度:因为只遍历一次,所以O(n)
空间复杂度:满足题目要求