删除给出链表/数组中的重复元素

删除给出链表中的重复元素1

删除给出链表中的重复元素(链表中元素从小到大有序),使链表中的所有元素都只出现一次

例如:

给出的链表为1->1->2,返回1->2.

给出的链表为1->1->2->3->3,返回1->2->3.

解题思路:

1.先判空

2.如果当前节点和当前节点下一个节点不为空

情况一:当前节点和当前节点下一个节点值相等,改变指针cur.next=cur.next.next;

情况二:继续如期遍历

import java.util.*;
/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */
public class Solution {
    /**
     *
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        if(head==null){
            return null;
        }
        ListNode cur=head;
        while(cur!=null &&cur.next!=null){
            if(cur.val==cur.next.val){
                cur.next=cur.next.next;
            }else{cur=cur.next;
            }
            
            
        }
        return head;
    }
}

删除给出链表中的重复元素2

 

给出一个排好序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。

例如:

给出的链表为1->2->3->3->4->4->5, 返回1->2->5.

给出的链表为1->1->1->2->3,  返回2->3.

 

去重,用一个哈希表记录每个值出现的频率就可以了。

解题思路:

1.hashmap记录每个节点出现的频数

2.将hashmap中的只出现一次的键放到arr中,去重

3.将arr排序从小到大

4,把数组里的值放到新建链表中,返回新建链表

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */

public class Solution {
    /**
     *
     * @param head ListNode类
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        HashMap<Integer,Integer> hashmap=new HashMap<>();//用来记录每个点出现的频数
        ArrayList<Integer> arr =new ArrayList<>();
        ListNode cur=head;
        //hashmap记录每个节点出现的频数
        while(cur!=null){
            int val=cur.val;
            if(hashmap.containsKey(val)){
                hashmap.put(val,hashmap.get(val)+1);
            }else{
                hashmap.put(val,1);
            }
            cur=cur.next;
        }
        //将hashmap中的只出现一次的键放到arr中,去重
        //keySet为键集合
        for(Integer i:hashmap.keySet()){
            if(hashmap.get(i)==1){
                arr.add(i);
            }
        }
        //将arr排序从小到大
        Collections.sort(arr);
        //新建一个ListNode,用来存放不重复的数
        ListNode newhead=new ListNode(-1);
        ListNode p=newhead;
          for(Integer i:arr){
              //把数组里的值放到节点中,
              ListNode node=new ListNode(i);
               p.next=node;
               p=p.next;
           }
        //切记返回newhead.next,newhead节点值为-1
          return newhead.next;
    }
}

法二:双指针的方式

解题思路:

1.新建一个头节点指向head

2.a=newhead为哑结点,b=head

3.比较a.next.val!=b.next.val值,不等,a,b向前移动

4.相等,b移动,直到不等, a.next=b.next;连接起来链表,b移动

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */

public class Solution {
    /**
     *
     * @param head ListNode类
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        ListNode newhead=new ListNode(-1);//新建一个头结点
        newhead.next=head;
        ListNode a=newhead;//a指向哑结点
        ListNode b=head;//b在a后面

        while(b!=null&&b.next!=null){
            if(a.next.val!=b.next.val){
                a=a.next;
                b=b.next;
            }else{
                //当a.next.val==b.next.val相等,移动b,
                while(b!=null&&b.next!=null&&a.next.val==b.next.val){
                    b=b.next;
                }
                a.next=b.next;
               b=b.next;
            }
        }

          return newhead.next;
    }
}

删除给出链表中的重复元素3

如果数组中元素最多允许重复两次呢?

例如:

给出有序数组 A =[1,1,1,2,2,3],

你给出的函数应该返回length =5,  A 变为[1,1,2,2,3].

法一::删除多余的重复项T(N*N),O(1)

解题思路:

1.使用两个变量,i 是遍历数组的指针,count 是记录当前数字出现的次数。count 的最小计数始终为 1。

2.从索引 1 开始一次处理一个数组元素

3.若当前元素与前一个元素相同,即 nums[i]==nums[i-1],则增加计数 count++。若 count > 2,则说明遇到了多余的重复元素 ,要从数组中删除它。由于我们知道这个元素的索引,可以使用 del,pop 或 remove 操作(或你选择语言支持的任何相应的操作)从数组中删除它。由于删除了一个元素,所以我们的索引应该要减一。

4.若当前元素与前一个元素不相同,即 nums[i] != nums[i - 1],说明我们遇到了一个新元素,则更新 count = 1

5.由于我们从原始数组中删除了所有多余的重复项,所以最终在原数组只保留了有效元素,返回数组长度

import java.util.*;
public class Solution {
//删除对应下标的值,元素前移
    public int[] delete(int []A,int index){
        for(int i=index+1;i<A.length;i++){
            A[i-1]=A[i];
        }
        return A;
    }
    public int removeDuplicates(int[] A) {
         int count=1; //初始化每个元素只有一个
         int i=1;
         int length=A.length;
         while(i<length){
//如果元素相等
             if(A[i]==A[i-1]){
                 count++;
                 if(count>2){
                     this.delete(A,i);
                     i--;
                     length--;//删除一个,长度减一
                      }
                 }else{
                     count=1;//只出现过一次
                 }  
                 i++;//继续下一个
             }                  
         return length;
    }
}

法二:覆盖多余的重复项T(N),O(1)

 

解题思路:

1.两个指针,i 是遍历指针,指向当前遍历的元素;j 指向下一个要覆盖元素的位置。

2. count 记录当前数字出现的次数。count 的最小计数始终为 1。

3.我们从索引 1 开始一次处理一个数组元素。

4.若当前元素与前一个元素相同,即 nums[i]==nums[i-1],则 count++。若 count > 2,则说明遇到了多余的重复项。在这种情况下,我们只向前移动 i,而 j 不动。

5.若 count <=2,则我们将 i 所指向的元素移动到 j 位置,并同时增加 i 和 j。

6.若当前元素与前一个元素不相同,即 nums[i] != nums[i - 1],说明遇到了新元素,则我们更新 count = 1,并且将该元素移动到 j 位置,并同时增加 i 和 j。

7.当数组遍历完成,则返回 j。

import java.util.*;
public class Solution {  
    public int removeDuplicates(int[] A) {
         int count=1;
         int j=1;
         int length=A.length;
         for(int i=1;i<length;i++){
             if(A[i]==A[i-1]){
                 count++;
             }else{
                 count=1;
             }
             if(count<=2){
                 A[j++]=A[i];                 
             }            
         }
         return j;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值