小丁leetcode刷题日记之链表

T24

首先我自然想到迭代的方法,这个方法挺笨的,没啥新意。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null||head.next==null)
            return head;
        ListNode prev = head;
        ListNode cur = head.next;
        int count = 2;
        while (cur!=null){
            if (count%2==0){
                int temp= cur.val;
                cur.val = prev.val;
                prev.val=temp;
            }
            count++;
            cur=cur.next;
            prev=prev.next;
        }
        return head;
    }
    
}

就简单记录一下。

接下来是递归的方法,我发现链表挺适合用递归方法解决的。

class Solution {
    public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = head.next;
        head.next = swapPairs(newHead.next);
        newHead.next = head;
        return newHead;
    }
}

我使用递归时假定,这个函数的功能已经完善了,只想第一个递的过程,不要想归的过程,会把自己想糊涂的。

边界条件,就是只有一个节点或者节点为空的时候

原始为2  1   3   4

图中第二步为

ListNode newhead = head.next

定义新头指针

图中第三步

        head.next = swapPairs(newHead.next);

 把旧的头节点的指针指向后边排序好的

图中第四步

 newHead.next = head;

把新头节点的指针指向旧节点,这样就实现了交换

T160

正常思路,先是想怎么找到相交节点,笨方法就是遍历,一个指针来回遍历,一个指针慢慢移动,直到找到相交的节点,这个方法太笨了。不妨这样想,A链表有5个节点,B链表6个节点。那么他们相交节点一定不是B链表的第一个。也就是说他们的相交节点,得从B节点第二个开始找。所以可以让B节点先移动1个节点,然后A和B一起动。如果有相交节点,那么在链表走完之前,一定能找到。推广来说,A链表为n个节点,B链表为m个节点。假设m>n,就先让B节点走m-n个节点,然后二者再一起走。

我自己写的代码太长了,膜拜下大佬写的代码,真的nb。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) return null;
    ListNode pA = headA, pB = headB;
    while (pA != pB) {
        pA = pA == null ? headB : pA.next;
        pB = pB == null ? headA : pB.next;
    }
    return pA;
}

T203 移除链表元素

我的思路,找到值就删除。

class Solution {
    public ListNode removeElements(ListNode head, int val) {
        ListNode curA;
        ListNode headA=new ListNode();
        headA.next = head;
        curA = headA;

       while(curA.next!=null && curA !=null ){
           if (curA.next.val==val){
               curA.next=curA.next.next;
           }else{
               curA=curA.next;
           }

       }
       return headA.next;

    }
}

主要学习一下递归的思路

对于给定的链表,首先对除了头节点head以外的节点进行删除,然后判断head的节点值是否等于val,如果head的节点值等于val,则head需要被删除,因此删除操作后的头节点为head.next。对head.next也进行上述操作,那么这就属于一个递归的过程。

递归终止的条件就是head为空,此时直接返回head。当head不为空,递归的进行删除操作。

class Solution {
    public ListNode removeElements(ListNode head, int val) {
       if(head == null)
           return head;
        head.next = removeElements(head.next,val);
        if(head.val==val)
            return head.next;

        else
            return head;
        

    }
}

T19删除链表的倒数第N个节点

我得思路,要删除倒数第n个节点。那我定义俩指针一个left,一个right,先让right指针走n个,然后俩指针再一起走,直到right.next指针指向null。这样left指向得指针就是要删除得倒数第n个节点

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
       ListNode headA = new ListNode();
       headA.next=head;
       ListNode left=headA;
       ListNode right=headA;
      ;
        for (int i = 0; i < n; i++) {
            right=right.next;
        }
        while (right.next!=null){
            left=left.next;
            right=right.next;
        }
        left.next=left.next.next;

        return headA.next;
    }
}

 T21 合并两个有序链表

我的思路,迭代的方法。定义一个指针prev,如果curA<curB,那么就让指针指向curA,curA往后移动,指针往后移动。以此类推

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode curA = list1;
        ListNode curB = list2;

        ListNode preHead = new ListNode();
        ListNode prev =preHead;
        while (curA!=null && curB!=null){
            if (curA.val <= curB.val){
                prev.next=curA;
                curA=curA.next;
            } else  {
                prev.next=curB;
                curB=curB.next;
            }
            prev = prev.next;
        }
        prev.next=curA==null?curB:curA;

       return preHead.next;

    }
}

还是学习一下递归的思路。

如果l1链表为空,合并的话,直接返回l2.同理l2链表为空,返回l1。后边就是假设这个合并功能已经实现了,直接使用这个函数。

class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if(list1 == null)
            return list2;
        if(list2 == null)
            return list1;
        if(list1.val<list2.val){
            list1.next = mergeTwoLists(list1.next,list2);
            return list1;
        }else{
            list2.next = mergeTwoLists(list1,list2.next);
            return list2;
        }



    }
}

    T328  奇偶链表

我的思路就是先记下奇数的链表和偶数的链表,再把偶数节点的链表放在奇数链表的后边。

class Solution {
    public ListNode oddEvenList(ListNode head) {
        ListNode nodeOdd = new ListNode();
        ListNode nodeEven = new ListNode();

        if(head==null)
          return null;
        nodeEven=head;
        ListNode node = nodeEven;
        nodeOdd=head.next;
        ListNode nodeTmp = nodeOdd;
        
     

        while(nodeEven!=null&&nodeEven.next!=null&&nodeEven.next.next!=null){
            nodeEven.next=nodeOdd.next;
            nodeEven=nodeEven.next;
            nodeOdd.next=nodeEven.next;
            nodeOdd=nodeOdd.next;
        }
        nodeEven.next=nodeTmp;

        return node;
    }
}

难得和官方答案思路几乎一样

T92  反转链表Ⅱ

第一种方法,是迭代的思路。比较麻烦。大体思路就是将这个反转链表分成三个子步骤,第一步就是先将要反转的部分给分开,第二步再是将需要反转的链表进行反转,第三步就是将反转后的链表合并到原位置。注意要记录下分割前后的节点。

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {


        ListNode dummpy = new ListNode(-1);
        dummpy.next=head;
        head=dummpy;
        ListNode pre = head;
        for (int i = 0; i < left -1; i++) {
            pre = pre.next;
        }
        ListNode rightNode = pre;
        for (int i = 0; i < right-left+1; i++) {
            rightNode=rightNode.next;
        }
        ListNode leftNode = pre.next;
        ListNode curr = rightNode.next;


        pre.next = null;
        rightNode.next =null;


        ListNode preL = null;
        ListNode cur = leftNode;
        while (cur!=null){
            ListNode next = cur.next;
            cur.next = preL;
            preL = cur;
            cur = next;
        }


        pre.next=rightNode;
        leftNode.next = curr;

        return head.next;
    }
}

 重点就是理解如何反转子链表。

第二种思路是递归

class Solution {
    ListNode successor = null;
    public ListNode reverseBetween(ListNode head, int left, int right) {
        if(left == 1)
        {
            return reverseN(head,right);
        }
           
        head.next=reverseBetween(head.next,left-1,right-1);
        return head;
        
       
    }
    ListNode reverseN(ListNode head,int n){
        if(n==1){
            successor = head.next;
            return head;
        }
        ListNode last = reverseN(head.next,n-1);
        head.next.next=head;
        head.next=successor;
        return last;
    }
}

如果从头开始反转,那么就和普通反转链表一样,直接调用reverseN(),如果不是从头反转,那么我们将其要反转的部分,看作头节点,也相当于从头反转。这样就可以递归调用。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值