算法训练 Day 4 | 链表:24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面试题 02.07. 链表相交,142.环形链表II

1. 两两交换链表中的节点

  • 第一想法:创建虚拟头指针,然后模拟
  • 看到题解想法:思路差不多
  • 遇到困难:循环内指针pre与n需要更新
public ListNode swapPairs(ListNode head) {
        ListNode vHead = new ListNode(-1);
        vHead.next = head;
        // 循环语句条件包括了该两种情况
        // if (head == null || head.next == null) return head;
        ListNode pre = vHead;
        ListNode n = head;

        while (n != null && n.next != null) {
            ListNode aft = n.next;
            pre.next = n.next;
            n.next = aft.next;
            aft.next = n;
            // 先给pre赋值为n,后更新n
            pre = n;
            n = n.next;
            
        }
        return vHead.next;

    }
  • 总结与收获:熟悉了虚拟头结点的使用,用时10min

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

  • 第一想法:一开始想到的是两次遍历,第一次算出节点总数,第二次找到倒数位置
  • 看到题解想法:快慢指针比两次遍历运算速度快一些些,但是时间复杂度都是O(n)
  • 遇到困难:快慢指针间隔的元素个数想了一阵子
1/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeNthFromEnd(head *ListNode, n int) *ListNode {
    vHead := &ListNode {Val: -1, Next: head}
    /** vHead := &ListNode {
        Val: -1, 
        Next: head,
    }**/
    pre, curr, aft:= vHead, head, head
    //快指针先往右移动n
    for i := 0; i < n; i++ {
        if aft == nil && i < n - 1 {
            return nil;
        }
        aft = aft.Next
    }
    // 快慢指针一起移动,aft移动到最右
    for aft != nil {
        pre = pre.Next;
        curr = curr.Next;
        aft = aft.Next;
    }
    //删除当前节点
    pre.Next = curr.Next

    return vHead.Next;

}
  • 总结与收获:由于学习需要,本题尝试使用Go语言编写,以练习Go语言语法知识,如:
    1. Go语言结构体单行赋值如代码所示,分行赋值需要在最后一条语句加逗号
    2. 循环语句都使用for,代替Java的while
    3. 变量声明赋值时,使用:=符号

3. 链表相交

  • 第一想法:一刷时使用了哈希表进行解题;二刷知道规律
  • 看到题解想法:和题解解法相似
  • 遇到困难:使用标志位进行保存
1/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func getIntersectionNode(headA, headB *ListNode) *ListNode {
    a, b := headA, headB
    aFlag, bFlag := false, false
    // 空链表直接返回null
    if headA == nil || headB == nil {
        return nil;
    }

    for !((aFlag == true && a == nil) || (bFlag == true && b == nil)) {
        if a == b {
            return a
        }
        a = a.Next
        b = b.Next
        if a == nil && aFlag == false {
            aFlag = true
            a = headB
        }
        if b == nil && bFlag == false {
            bFlag = true
            b = headA
        }
    }
    return nil;
}
  • 总结与收获:用时20min

4. 环形链表II

  • 第一想法:一刷想到用HashSet来判断是否存在重复元素,第一个出现的重复元素即为环形起点
  • 看到题解想法:通过slow和fast指针来写,是另一种巧妙的方法,空间复杂度较低
  • 遇到困难:公式推导没记住,不熟练
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func detectCycle(head *ListNode) *ListNode {
    slow, fast := head, head
    for fast != nil && fast.Next != nil {
        slow = slow.Next
        fast = fast.Next.Next
        if fast == slow {
            var n1, n2 *ListNode
            n1 = head
            n2 = slow
            for n1 != n2 {
                n1 = n1.Next
                n2 = n2.Next
            }
            return n1
        }
    }
    return nil;
}
  • 总结与收获:用时30min

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值