看题:
注意:不仅要输出长度,而且要给数组排序,不可有重复。
由于数组中元素已经有序,那么重复元素一定在一起,找出他们不难,我们会在外层循环中先找打它,然后用delete方法,删除这个元素,但是从数组中删除元素的时间复杂度为O(n),因为两层循环嵌套,时间复杂度就为O(n^2).
这是因为数组在中间删除元素的时间复杂度为O(n),而在数组尾部删除的时间复杂度为O(1),因而一个算法思想就是将数组中重复的元素移到后面去。
我们让慢指针slow
从0开始,快指针fast从1开始
,找到一个不重复的元素就告诉slow
并让slow
前进一步。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp6
{
class Program
{
static void Main(string[] args)
{
string a = Console.ReadLine();
int[] arr = new int[a.Length];
for (int i = 0; i < a.Length; i++)
{
arr[i] = Convert.ToInt32(a.Substring(i, 1));
}
Console.WriteLine(removeDuplicate(arr));
}
static int removeDuplicate(int[] nums)
{
if(nums.Length == 0) { return 0;}
int slow = 0, fast = 1;
while(fast < nums.Length)
{
if(nums[fast] != nums[slow]){
slow++;
nums[slow] = nums[fast];
}
fast++;
}
return slow + 1;
}
}
}
对于链表的操作其实也是一样的:
static Node RemoveDuplicate(Node head)
{
Node slow = head;
Node fast = head.next;
while (fast != null)
{
if (slow.val != fast.val)
{
slow = slow.next;
slow.val = fast.val;
}
fast = fast.next;
}
slow.next = null;
return head;
}
当然,由于链表删除元素为O(1),所以也可以找到它,然后删掉它:
static Node RemoveDuplicate(Node head)
{
Node current = head;
while(current.next != null)
{
if(current.val != current.next.val)
{
current = current.next;
}
else
{
Node tempnode = current;
while (true)
{
tempnode = tempnode.next;
if(tempnode.val != tempnode.next.val)
{
break;
}
}
current.next = tempnode.next;
}
}
return head;
}
但是相比之下,本文介绍快慢指针的方法还是更棒一些哈~其实,对于数组相关的算法问题,有一个通用的技巧:要尽量避免在中间删除元素,那我就先想办法把这个元素换到最后去。
摘自公众号:labuladong