【LeetCode】链表(一)

1、 删除链表中等于给定值 “val” 的所有节点。

        解题思路:先考虑特殊情况,当链表为空直接返回null,想要删除指定元素则需遍历一遍链表,从第二个节点开始遍历,如果从第一个节点开始遍历,第一个节点的prev会出现空指针异常,此时创建两个结点cur用于遍历和prev用于删除,如果cur的值等于val, 利用prev删除cur,如果cur的值不等于val,则cur、prev都向后走一步,最后再回过头来看head的值是否为val,最终返回链表头节点head。

public ListNode removeElements(LinkedNode head,int val){
    if(head==null){
        return null;
    }
    //1.先删非头结点
    LinkedNode prev = head;
    LinkedNode cur=head.next;
    while(cur!=null){
        if(cur.val==val){
            //删除
            prev.next=cur.next;
            cur=prev.next;
        }else{
            //跳过
            prev=cur;
            cur=cur.next;
        }
    }
    //2.再删头节点
    if(head.val == val){
        head=head.next;
    }
    return head;
}

2、反转一个单链表。 

       解题思路:首先考虑两种特殊情况,一是为空链表时,直接返回null即可,二是当链表中只含有一个元素时,不需要进行特殊处理返回head即可。下面处理普通情况,首先定义一个新结点newHead作为反转后链表的头结点,初始化为null,但不意味着指向null,再分别定义三个结点,cur指向头结点,prev初始化为空,next保存cur的下一个结点。

        把当前对象cur的下一个指向prev,再将prev 赋值给cur,然后cur赋值为下一个对象next,即可完成反转操作,之后仅需循环重复该操作。

    当next为空时意味着链表结束(cur.next == null),此时的cur为反转后链表的头结点即newHead,最终返回newHead得到反转后的单链表。

public ListNode reverseList(ListNode head){
    if(head == null){//空链表
        return null;
    }
    //对于只有一个元素的链表,不需要处理
    if(head.next=null){
        return head;
    }
    //处理多个元素情况
    ListNode newHead=null;
    ListNode cur=head;
    ListNode prev=null;
    while(cur!=null){
        ListNode next=cur.next;
        if(next==null){
            newHead=cur;
        }
        //翻转指针指向
        cur.next=prev;
        prev=cur;
        cur=next;
    } 
    return newHead;
}

3、给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

        解题思路:将头结点head传给size()函数,求得链表长度,定义变量steps为长度一半即steps=size(head)/2,创建一个新的结点指向头结点cur,利用for循环使cur向后走steps次,最后返回cur即为链表的中间结点。

public ListNode middleNode(ListNode head){
    //1.得到链表长度
    int steps = size(head)/2;
    ListNode cur=head;
    for(int i=0;i<steps;i++){
        cur=cur.next;
    }
    return cur;
}
public int size(ListNode head){
    int size =0;
    for(ListNode cur = head;
        cur != null;cur = cur.next){
            size++;
    }
    return size;
}

4、输入一个链表,输出该链表中倒数第k个结点。

      解题思路:此题与第三题求中间结点思路大致相同,但具体使cur向后移动的步数略有不同,求倒数第K个结点时,总长度减去k即为需要走的步长,最终依旧是返回cur,便可得到倒数第K个结点。

       另:此类题若用C语言解决,可使用:“快慢指针”法,快指针先走K步,然后两个指针同时后移,当快指针到达终点时,则慢指针就处于倒数第K个结点位置处。如果是解决求中间结点位置,则让快指针一次走两步,慢指针一次走一步,最终快指针到达终点时,慢指针即处于链表的中间位置。

public ListNode FindKthToTail(ListNode head,int k){
    int length=size(head);
    if(head==null || k<=0 || k>length){
        return null;
    }
    //总长度减去k即为需要走的步长
    int offset=length-k;
    ListNode cur=head;
    for (int i = 0; i < offset; i++) {
        cur=cur.next;
    }
    return cur;
}
public int size(ListNode head){
    int size =0;
    for(ListNode cur = head;
        cur != null;cur = cur.next){
            size++;
    }
    return size;
}

5、 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

        解题思路:创建节点cur1,cur2分别遍历两个链表,newHead为合并后链表的头部,newTail为合并后链表的尾部,

        如果L1的值小于L2则将L1元素添加至新链表,并且newTail向后移动,同理,直到最后有一方结束,则将未结束的指直接合并至新链表结尾,因为合并的是有序链表,若一开始有一方链表为空,直接返回不为空的即可。

public ListNode mergeTwoList(ListNode L1,ListNode L2){
    ListNode cur1 = L1;
    ListNode cur2 = L2;
    ListNode newHead = null;
    ListNode newTail = null;
    if(L1 == null){
        return L2;
    } 
    if(L2 == null){
        return L1;
    }
    while(cur1!=null && cur2!=null){
        if(cur1.val<cur2.val){
            if(newHead == null){
                newHead = cur1;
                newTail = cur1;
                cur1 = cur1.next;
            } else {
                newTail.next=cur1;
                newTail=newTail.next;
                cur1=cur1.next;
            }
        } else {
            if(newHead == null){
                newHead = cur2;
                newTail = cur2;
                cur2 = cur2.next;
            } else {
                newTail.next=cur2;
                newTail=newTail.next;
                cur2=cur2.next;
            }
        }
        if(cur1 == null){
            newTail.next=cur2;
        } else {
            newTail.next=cur1;
        }
    }
    return newHead;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值