首先要链表的node类。
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
83: Remove Duplicates from Sorted List删除有序链表中重复元素
思路:由于链表是有序的,只需要定义一前一后两个对象q,p。如果两个对象所指向的元素相等,则去掉一个就可以了。
/**
* 删除有序链表重复元素
* @param head
* @return
*/
public ListNode deleteDuplicatesForSortedList(ListNode head) {
if(head==null||head.next==null)
return head;
ListNode q = head.next; //q在前
ListNode preq = head; //preq在后
while(q != null){
if(preq.val==q.val){ //相等则去掉q指向的元素
preq.next = q.next;
q = q.next;
}else{
preq = q;
q = q.next;
}
}
return head;
}
此题的变种自然就是删除无序链表中的重复元素。
思路:由p从第一个元素开始遍历,当其指向第一个元素时,q以及指向其前一个元素的preq开始遍历整个链表找到相同的元素就删掉。
public ListNode deleteDuplicates(ListNode head) {
ListNode p = head;
ListNode q = head;
ListNode preq = null;
if(head==null)
return head;
while(p.next != null){ //遍历链表
q = p.next; //q从p的下一个元素开始
preq = p;
while(q!=null){ //直到q为null而不是q.next!=null
if(p.val==q.val){
preq.next = q.next;
q = q.next;
}else{
preq = q;
q = q.next;
}
}
if(p.next!=null)
p = p.next;
}
return head;
}
删除链表中指定元素,用两个指针遍历,对比,删除。代码如下。
public ListNode removeElements(ListNode head, int val) {
if(head == null)
return head;
ListNode p = head;
ListNode prep = null;
while(p!=null){
if(p.val==val){
if(head==p){ //删除第一个节点的情况,此时prep为null,得单独处理
head = p.next;
if(head==null)
return head;
}else{
prep.next = p.next;
}
}else{
prep = p;
}
p = p.next;
}
return head;
}
19:removeNthFromEnd删除从结尾数第n个元素。
两个指针p,q,p先走n步,然后一起走直到队尾。删掉q指向的元素就可以了。
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p=head;
ListNode q=head;
ListNode tmp=null;
for(int i=1;i<n;++i){
q = q.next;
}
while(q.next!=null){
q = q.next;
tmp = p;//tmp指向待删除节点前一个节点
p = p.next; //p指向待删除节点
}
if(tmp==null){
head = p.next;
}else{
tmp.next = p.next;
}
return head;
}
206:逆置链表。
将链表的指针全部转向。好比p在前q在后,q=p.next;就可以了。
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null)
return head;
ListNode p = head.next;
head.next = null;
ListNode q = head;
ListNode tmp =null;
while(p != null){
tmp = p.next;
p.next = q;
q = p;
p = tmp;
}
return q;
}
21:合并两个有序链表。
对两个链表从头开始遍历,一个作为主链表,一个作为待插入链表。当待插入链表元素大于主链表时,插入。
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null&&l2==null)
return null;
if(l1==null&&l2!=null)
return l2;
if(l1!=null&&l2==null)
return l1;
ListNode p = l1;
ListNode q = l2;
if(l1.val>l2.val){
p = l2; //p指向第一个值较小的链表,主表
q = l1; //q指向较大的,待插入链表
}
ListNode prep = null;
while(p!=null){
if(q!=null&&q.val<p.val){
prep.next = q;
//遍历待插入链表,找到第一个小于p元素的,这中间的一段元素都需要插入到主表
while(q!=null&&q.val<p.val){
prep = prep.next;
q = q.next;
}
prep.next = p;;
}
prep = p;
p = p.next;
}
prep.next = q;
if(l1.val>l2.val){
return l2;
}else{
return l1;
}
}