删除给出链表中的重复元素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;
}
}