刷题-链表-API及套路总结

一、链表-简单-API及套路总结

1、链表-简单-约7题

1)206.反转链表
【题目特点】:  
【原理】: 移动双指针/递归
	迭代:使pre=null,cur=head,每次循环,申请临时节点存储当前节点的下一位,即,tmp=cur.next。
然后将当前节点的下一位指向pre,即cur.next = pre,断开连接。当前节点赋值上一节点,即pre=cur。
同时,临时节点赋值给当前节点,cur=tmp,这样两个指针完成一步移动。循环往返,当cur为null,此时pre指向尾部即头节点。
	递归:先不断递归到尾部,然后返回尾结点。
同时head.next.next = head,将尾部指向上一个节点,head.next = null,上一个节点的下一个置为null。
最后每次返回尾结点,即头节点(倒转后)。
【套路】: 
ListNode tmp = cur.next;
cur.next = pre ;
pre = cur ;
cur = tmp;

【复杂度】:时间复杂度为O(n),空间复杂度为O(1).
ListNode tmp = cur.next;//申请临时存储节点
cur.next = pre;//将下一位反向指向第一位
pre = cur;//移动第一位,从而第三位指向第二位
cur = tmp;//移动当前第二位往前移动一位,从而真实第二位反指向第一位实现反转
2)21. 合并两个有序链表
【题目特点】:  
【原理】: 递归或双指针。与合并两个数组原理类似,类似双指针法,将较小的数值移动到临时存储空间内
【复杂度】:时间复杂度为O(n+m),空间复杂度为O(1).

写法套路

  ListNode head = new ListNode(-1); 创建空头节点
  ListNode tmp = head;//将头节点赋予临时节点,同时临时节点作为移动指针不断移动。
  while(l1!=null&&l2!=null){}
  tmp.next=l1==null?l2:l1;// 合并后 l1 和 l2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
3)141. 环形链表
【题目特点】:  
【原理】: 1、定义快慢指针,定理,若是环形链表,则快慢指针会相遇。
		  2、哈希表,遍历并添加到set集合中,若有重复则返回true,若最终为null,则不是环。
【复杂度】:时间复杂度为O(n),空间复杂度为O(1).
4)剑指 Offer 22. 链表中倒数第k个节点
【题目特点】:  
【原理】: 第一想法是先遍历整个链表求出长度,最后遍历n-k。不推荐
		  可以利用双指针的思想,1、先让快指针前进k步。
		  					2、快慢指针同时前进n-k步(即快指针的移动到尾端,此时慢指针移动了n-k),
此时慢指针所在位置为倒数第k个节点。
【复杂度】:时间复杂度为O(n),空间复杂度为O(1).
5)剑指 Offer 06. 从尾到头打印链表
【题目特点】:  
【原理】: 利用栈的思想,遍历链表压栈,最后再弹栈,同时存储到数组中返回。
【复杂度】:时间复杂度为O(n),空间复杂度为O(1).
  Stack<ListNode> stack = new Stack<ListNode>();
        ListNode temp = head;
        while (temp != null) {
            stack.push(temp);
            temp = temp.next;
        }
        int size = stack.size();
        int[] print = new int[size];
        for (int i = 0; i < size; i++) {
            print[i] = stack.pop().val;
        }
        return print;
6)234. 回文链表
【题目特点】:  
【原理】: 思路一:复制链表值到数组列表中,使用双指针法判断是否为回文。
		  思路二:递归
		  思路三:快慢指针。找到中间位置,偶数为右边位置,奇数为中间,然后传参将链表的后半部分反转(修改链表结构),然后将前半部分和后半部分进行比较。比较完成后将链表再反转回来。
【复杂度】:时间复杂度为O(n),空间复杂度为O(1).

套路:快慢指针可以找到链表的中间。

  if (head == null) {
            return true;
        }
        // 找到前半部分链表的尾节点并反转后半部分链表
        ListNode firstHalfEnd = endOfFirstHalf(head);
        ListNode secondHalfStart = reverseList(firstHalfEnd.next);
        // 判断是否回文
        ListNode p1 = head;
        ListNode p2 = secondHalfStart;
        boolean result = true;
        while (result && p2 != null) {
            if (p1.val != p2.val) {
                result = false;
            }
            p1 = p1.next;
            p2 = p2.next;
        }        
        // 还原链表并返回结果
        firstHalfEnd.next = reverseList(secondHalfStart);
        return result;
    }
    private ListNode endOfFirstHalf(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
    private ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

2、刷题总结

基本上最常用的为快慢指针即双指针来解题,其次为递归,但是一般递归可能现场有点反应不过来,
所以可以先采用双指针来解题。若遇到【引用重复】的含义即相同的节点、交点可以采用哈希表set集合来解。
从尾部遍历可想到栈的思想Stack.

快慢指针:【中间】

环形链表:可以理解成两个人速度一致, 走过的路程一致。那么肯定会同一个时间点到达终点。

二、链表-中等-API及套路总结

1、链表-中等-约12题

1) 2. 两数相加
【题目特点】: 移动指针+数学; 并进行相加,累计进位
【复杂度】:O(max(m,n)) , O(1)
【套路写法】:
//创建虚拟头节点,并新建一个复制一份方便移动。
		ListNode head = new ListNode(-1);
        ListNode cur = head;
//三目运算
		int n1 = l1!=null?l1.val:0;
//余数与商
        cur.next = new ListNode(sum % 10);
        carry = sum / 10;
【总结】:掌握余数和除数,掌握三目运算。掌握创造虚拟。   
2)19. 删除链表的倒数第 N 个结点
【题目特点】:属于快慢指针
【感想】:与简单题中返回倒数第n个节点类似,不过多了一步。
【复杂度】:O(n),O(1)
【套路写法】: 
			ListNode dummy = new ListNode(0, head);和下面二者一个道理
			ListNode dummyHead = new ListNode(0);
			dummyHead.next = head; 
【总结】:掌握创造虚拟节点
        掌握 [简单题中 返回倒数第n个节点],即:快指针从n开始走,走N-n,从而慢指针走了N-n,就走到倒数n个节点。
        掌握 删除下一个节点:second.next = second.next.next;
3)24. 两两交换链表中的节点
【题目特点】: 属于交换链表
【解题方法】:递归或是迭代,迭代的大致思路是创建三个节点,一个主节点,两个临时节点,通过来回交换,从而移动两个节点的位置。注意是位置而不是节点的值 
【复杂度】:O(n),O(1)
【套路写法】: 
//创建虚拟节点,或是头节点,令其下一位指向头节点,这样做的好处是移动的时候可以,刚好移动目标点位之前,从而方便做一些操作。最后结束返回dummyHead.next;完美
			ListNode dummyHead = new ListNode(0);
			dummyHead.next = head; 
			return dummyHead.next;
// 交换两个节点的位置的套路
			temp.next = node2;
            node1.next = node2.next;
            node2.next = node1;
            tmp = node1;
【总结】:掌握创造虚拟节点。
		 掌握交换两个节点的写法。
4)92. 反转链表 II
 【总结】:该题与简单题类似,是简单题的升级版,简单题的反转是将整个链表反转,而该题是将中间一部分进行反转。
 		但是该题是头插,移动并往头部插入节点,和简单题稍微有点不太一样。

	next = cur.next;
	cur.next = next.next;
	next.next = pre.next;
	pre.next = next;
5)61. 旋转链表
【题目特点】:移动链表,和两数相加都用到取余操作
【原理】:
【套路写法】:
		 int add = n - k % n;//计算移动k个元素,移动前面的个数,计算从哪个断开	 
		 
6)142. 环形链表 II
7)82. 删除排序链表中的重复元素 II
【题目特点】:
【原理】:核心点是创造哑节点,并比较下一个和下下个,一样的话赋值给x,并循环比较同时删除
【套路写法】:
8)146. LRU 缓存机制
9)148. 排序链表
10)86. 分隔链表
【题目特点】:
【原理】:核心点是创造小链表和大链表,将小于该数存到小链表里,将大于等于改数存到大链表里。最后将大链表置空,将小链表的next指向大链表头部。
【套路写法】:

2、套路总结

感觉中等题目,比简单题目,多了一步操作。原理还是简单题的组合。
很多题都创造哑节点,比较下一位和下下位
模板
【题目特点】:
【解题API】:
【解题核心】: 
【原理】:
【提升解析】: 
【拓展点】: 
【复杂度】:
【套路写法】:
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值