LeetCode 线性表的操作(Remove Duplicates)

    

    LeetCode  :点击这里进入LeetCode

    

    本文内容 :线性表的操作 相关题目  (数组,单链表,双向链表等)


    1.Remove Duplicates from Sorted Array


    原文链接:点击这里进入


    基本内容:

    Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.

    Do not allocate extra space for another array, you must do this in place with constant memory.

    For example,
    Given input array A = [1,1,2],

    Your function should return length = 2, and A is now [1,2].
    

    解题思想:

    
    本题目就是让你来实现一个去除数组中重复的函数。由于数组是排序好的数组,这样就可以从头向后扫描整个数组。数组第i个位置应该存放的值应该是数组中第i个大小的值。那么如何删除重复的值呢。设置一个index,让a[i]与a[index]比较。(i大于index)代码如下:
 
    解法1:
class Solution {
public:
    int removeDuplicates(int A[], int n) 
    {
         if( n == 0  )
            return 0;
        int index = 0;    
        for( int i = 1; i < n; i++ )//scan the sorted array 时间复杂度o(n),空间复杂度o(1).
        {
            if( A[ index ] != A[ i ] )
            {
                A[ ++index ] = A[ i ];
            }
        }
        return index + 1;
    }
};

    解法2: 我们知道在STL中有一个函数叫做unique,它的功能是去除相邻的重复元素(只保留一个),还有一个容易忽视的特性是它并不真正把重复的元素删除。我们可以首先看一下它的实现代码:
    
    
/**
   *  @brief Remove consecutive duplicate values from a sequence.
   *  @ingroup mutating_algorithms
   *  @param  __first  A forward iterator.
   *  @param  __last   A forward iterator.
   *  @return  An iterator designating the end of the resulting sequence.
   *
   *  Removes all but the first element from each group of consecutive
   *  values that compare equal.
   *  unique() is stable, so the relative order of elements that are
   *  not removed is unchanged.
   *  Elements between the end of the resulting sequence and @p __last
   *  are still present, but their value is unspecified.
  */
  template<typename _ForwardIterator>
    _ForwardIterator
    unique(_ForwardIterator __first, _ForwardIterator __last)
    {
      // concept requirements
      __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<
				  _ForwardIterator>)
      __glibcxx_function_requires(_EqualityComparableConcept<
		     typename iterator_traits<_ForwardIterator>::value_type>)
      __glibcxx_requires_valid_range(__first, __last);

      // Skip the beginning, if already unique.
      __first = _GLIBCXX_STD_A::adjacent_find(__first, __last);//找到第一个前后位置上元素相同的位置,并且返回第一个的位置
      if (__first == __last)
	return __last;

      // Do the real copy work.
      _ForwardIterator __dest = __first;//向后移动元素
      ++__first;
      while (++__first != __last)
	if (!(*__dest == *__first))
	  *++__dest = _GLIBCXX_MOVE(*__first);
      return ++__dest;
    }

    看过源代码才会感慨,大师就是大师。代码是一种艺术。
    这样我们可以通过STL中的函数来帮助我们实现去除重复元素,代码:
    
int removeDuplicates( int A[], int n )
{
    return distance( A, unique( A, A + n ) );
}
    distance函数用来计算个数。看完unique的源代码,忍不住自己手痒写了一个自己的。(模仿,贱笑了)
    
template<typename _ForwardIterator>
    _ForwardIterator
    uniqueExample(_ForwardIterator __first, _ForwardIterator __last)
    {
    //__last 是元素最后一个元素的下一个位置.
        if( __first == __last )
            return __last;
        _ForwardIterator __next = ++__first;
        while( !( __next++ == __last ) )
        {
            if( *__next != * __first )
            *++__first = *__next;
        }
        return __first;
    }


int removeDuplicates( int A[], int n )
{
    return distance( A, uniqueExample( A, A + n ) );
}
    
   

    2.Remove Duplicates from Sorted Array II

    原文链接:点击这里进入


    基本内容:

    Follow up for "Remove Duplicates":
    What if duplicates are allowed at most twice?

    For example,
    Given sorted array A = [1,1,1,2,2,3],

    Your function should return length = 5, and A is now [1,1,2,2,3].

    解题思想:

    与上题类似,只需要加一个变量的值记录其中元素出现的个数。

    代码:
     
int removeDuplicates(int A[], int n) {
        if( n == 0 || n == 1 )
        return n;
        int index = 0;
        int num = 1;//用来记录元素出现的次数,初始为1
        for( int i = 1; i < n; i++ )
        {
            if( !( A[ i ] == A[ index ] ) )
            {
                A[ ++index ] = A[ i ];
                num = 1;
            }
            else
            {
                if( num == 1 )
                {
                    ++num;
                    A[ ++index ] = A[ i ];
                }
            }
        }
        return index + 1;



    上面两个题目是对数组来进行操作,下面我们看两个对链表进行操作的题目:
    

   3.Remove Duplicates from Sorted List


    原文链接:点击这里进入  


    基本内容:

    Given a sorted linked list, delete all duplicates such that each element appear only once.

    For example,
    Given 1->1->2, return 1->2.
    Given 1->1->2->3->3, return 1->2->3.

    解题思想:

    定义两个指针,一前一后,往后扫描。如若相同,则修改指针的指向。

    代码:
    
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *deleteDuplicates(ListNode *head) {
        if( NULL == head || NULL == head -> next )
        return head;

        ListNode *pre = head;
        ListNode * current = head -> next;
        while( current != NULL )
        {
            if( current -> val != pre -> val )
            {
                pre = current;
                current = current -> next;
            }
            else
            {
                ListNode * p = current;
                pre -> next = current -> next;
                current = current -> next;
                delete p;
            }
        }
        return head;
        
    }
};



    
    
    

  4.Remove Duplicates from Sorted List II


    原文链接:点击这里进入


    基本内容:

    
    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

    For example,
    Given 1->2->3->3->4->4->5, return 1->2->5.
    Given 1->1->1->2->3, return 2->3.

    解题思想:


    定义三个指针,从前往后扫描,因为相同内容的指针需要全部删除掉,则需要找到3个位置,前面的位置,相同元素的起始位置和相同元素的最后一个位置的下一个位置。(需要讨论不同的情况)

    代码:

    

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *deleteDuplicates(ListNode *head) {
        if( NULL == head || NULL == head -> next )
            return head;
        ListNode * pre = head;
        ListNode * current = head;
        ListNode * nextPos = head -> next;
        while( NULL != nextPos )
        {
            if( nextPos -> val == current -> val )
            {
                while( NULL != nextPos && nextPos -> val == current -> val  )
                    nextPos = nextPos -> next;
                if( NULL == nextPos )
                {
                    if( current == pre )
                        return NULL;
                    else
                        pre -> next = NULL;
                }
                else
                {
                    if( current == pre )
                    {
                        head = nextPos;
                        pre = nextPos;
                        current = nextPos;
                        nextPos = nextPos -> next;
                    }
                    else
                    {
                        pre -> next = nextPos;
                        current = nextPos;
                         nextPos = nextPos -> next;
                    }
    
                }
            }
            else
            {
                pre = current;
                current = current -> next;
                nextPos = nextPos -> next;
            }
        }
        return head;
        
    }
};



    
    

    

    5.Remove Element


    原文链接:点击这里进入


    基本内容:

    Given an array and a value, remove all instances of that value in place and return the new length.

    The order of elements can be changed. It doesn't matter what you leave beyond the new length.

    解题思想:

    和第一道题目有点类似。区别是判断的时候不是前后判断了,而是和另外一个值判断。

    代码:
    
 int removeElement(int A[], int n, int elem) {
        
        if( n == 0 )
            return 0;
        int index = 0;
        for( int i = 0; i < n; i++ )
        {
            if( A[ i ] != elem )
                A[ index++ ] = A[ i ];
        }
        return index ;
    }


    

    6.Remove Nth Node From End of List


    原文链接:点击这里进入


    基本内容:

    
    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.

    For example,
    Given 1->2->3->3->4->4->5, return 1->2->5.
    Given 1->1->1->2->3, return 2->3.

    解题思想:


    删除从后往前数  第 n 个节点,这个其实就是 找到一个单链表中从后往前数第n个节点的一个变种。那个题目的解法是设置两个指针,一个slow ,一个fast,让fast 先走n-1 步,然后在一起走。fast 到达链表最后的时候,slow指向的节点正好是倒数第n个节点。  这里删除还需要用到倒数第n个节点的前面的一个节点,用来修改指针的指向。需要考虑到。删除的节点在头节点,超出头节点和其他部位。这3种情况,其实这种题目本身并不难,只是需要考虑到所有的情况。

    代码:
    
    
 ListNode *removeNthFromEnd(ListNode *head, int n) {
        if( NULL == head )
            return NULL;
        if( 0 == n )
            return NULL;
        if( n == 1 ) // 删除倒数第一个节点,分两种情况,只有一个节点和其他。
        {
            if( NULL == head -> next)
                return NULL;
            else
            {
                ListNode * s = head ;
                while(  NULL != s -> next -> next )
                    s = s -> next;
                ListNode * deleteNode = s -> next;
                s -> next = NULL;
                delete deleteNode;
                return head;
            }
        }
            
        ListNode * fast = head;
        for( int i = 0; i < n - 1; i++  )
        {
            fast = fast -> next;
            if( NULL == fast )
                return NULL;
        }
        if( fast ->next != NULL )
        {
            fast = fast -> next;
            ListNode *slow = head;
            while( NULL != fast -> next )
            {
                fast = fast -> next;
                slow = slow -> next;
            }
            slow -> next = slow -> next -> next;
        }
        else//head   
        {
            ListNode *s = head;
            head = head -> next;
            delete s;
            
        }
        
        return head;
    }


    OK,本问到此结束,如若以后有更好的解法,会及时更新上来。
    

      

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值