电信保温杯笔记——代码随想录 刷题攻略 链表
电信保温杯笔记——代码随想录 刷题攻略
代码随想录 刷题攻略
电信保温杯笔记——代码随想录 刷题攻略
1.关于链表,你该了解这些!
2.链表:听说用虚拟头节点会方便很多?
203.移除链表元素
使用伪头:
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyHead = new ListNode(0, head);
ListNode temp = dummyHead;
while (temp.next != null){
if(temp.next.val == val){
temp.next = temp.next.next;
}else {
temp = temp.next;
}
}
return dummyHead.next;
}
}
总结
伪头使用前提:需要定位一个节点的上一个节点并使用它的next指针。
3.链表:一道题目考察了常见的五个操作!
707.设计链表
class MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size = 0;
head = null;
}
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
ListNode temp = head;
while (index > 0){
temp = temp.next;
index--;
}
return temp.val;
}
public void addAtHead(int val) {
addAtIndex(0, val);
}
public void addAtTail(int val) {
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
if(index > size){
return;
}
ListNode dummyHead = new ListNode(0, head);
ListNode temp = dummyHead;
int loop = Integer.min(index, size);
while (loop > 0){
temp = temp.next;
loop--;
}
// 此时temp指向该删节点的上一个节点
ListNode newNode = new ListNode(val, temp.next);
temp.next = newNode;
size++;
head = dummyHead.next;
}
public void deleteAtIndex(int index) {
if (index >=0 && index < size){
ListNode dummyHead = new ListNode(0, head);
ListNode temp = dummyHead;
while (index > 0){
temp = temp.next;
index--;
}
// 此时temp指向该删节点的上一个节点
temp.next = temp.next.next;
head = dummyHead.next;
size--;
}
}
}
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val){
this.val = val;
}
ListNode(int val, ListNode next){
this.val = val;
this.next = next;
}
}
总结
如果要找索引为 index 的节点的话:
ListNode temp = head;
while (index > 0){
temp = temp.next;
index--;
}
// 此时temp就是要找的节点
如果要找索引为 index 的节点的上一个节点的话:
ListNode dummyHead = new ListNode(0, head);
ListNode temp = dummyHead;
while (index > 0){
temp = temp.next;
index--;
}
// 此时temp指向该删节点的上一个节点
如果增加或者删除节点后,一定要重新定位head节点
ListNode dummyHead = new ListNode(0, head);
ListNode temp = dummyHead;
使用temp变量进行增加或者删除节点操作后
head = dummyHead.next;
4.链表:听说过两天反转链表又写不出来了?
206.反转链表
方法1
三指针:last,cur,next
/**
* 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 reverseList(ListNode head) {
if(head == null){
return null;
}
ListNode last = null;
ListNode cur = head;
ListNode next = head.next;
while (next != null){
cur.next = last;
last = cur;
cur = next;
next = next.next;
}
cur.next = last;
return cur;
}
}
方法2
官方:也是使用三指针,但以cur作为循环条件
/**
* 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 reverseList(ListNode head) {
ListNode prev = null;
ListNode cur = head;
ListNode temp = null;
while (cur != null) {
temp = cur.next;// 保存下一个节点
cur.next = prev;
prev = cur;
cur = temp;
}
return prev;
}
}
5.链表:两两交换链表中的节点
24. 两两交换链表中的节点
/**
* 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){
return null;
}
if(head.next == null){
return head;
}
ListNode dummyHead = new ListNode(0, head);
ListNode prev = dummyHead;
ListNode cur1 = head;
ListNode cur2 = null;
ListNode temp = null;
while (cur1 != null){
cur2 = cur1.next;
if(cur2 == null){
break;
}else {
temp = cur2.next;
cur2.next = cur1;
cur1.next = temp;
prev.next = cur2;
prev = cur1;
cur1 = temp;
}
}
return dummyHead.next;
}
}
总结
这题和上题都使用了prev,cur,temp指针,不同的是上一题一开始prev = null,这题prev = dummyHead,关键在于有没有使用到prev.next指针,用到则需要使用伪头。并且最好以cur作为循环条件。
核心代码
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummyHead = new ListNode(0, head);
ListNode prev = dummyHead;
ListNode cur = head;
ListNode temp = null;
while (cur1 != null){
}
}
}
6.链表:删除链表的倒数第 N 个结点
19.删除链表的倒数第N个节点
/**
* 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 removeNthFromEnd(ListNode head, int n) {
int size = 1;
ListNode dummyHead = new ListNode(0, head);
ListNode prev = dummyHead;
ListNode cur = head;
while (cur.next != null){
cur = cur.next;
prev = prev.next;
size++;
}
if(n == 1){
prev.next = null;
return dummyHead.next;
}
prev = dummyHead;
cur = head;
while (size > n){
cur = cur.next;
prev = prev.next;
size--;
}
prev.next = cur.next;
return dummyHead.next;
}
}
7.链表:链表相交
面试题 02.07. 链表相交
方法1
2个链表都遍历,求出长度,和长度差,让长度长的链表先走长度差的遍历,然后2个链表再同时开始。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) {
return null;
}
int sizeA = 0;
ListNode curA = headA;
while (curA != null) {
curA = curA.next;
sizeA++;
}
int sizeB = 0;
ListNode curB = headB;
while (curB != null) {
curB = curB.next;
sizeB++;
}
curA = headA;
curB = headB;
int delta = Math.abs(sizeA - sizeB);
int residue = Integer.min(sizeA, sizeB);
if(sizeA > sizeB){
while (delta > 0){
curA = curA.next;
delta--;
}
}else {
while (delta > 0){
curB = curB.next;
delta--;
}
}
while (residue > 0){
if (curA == curB){
return curA;
}
curA = curA.next;
curB = curB.next;
residue--;
}
return null;
}
}
方法2
思路新奇,代码简洁
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode A = headA, B = headB;
while (A != B) {
A = A != null ? A.next : headB;
B = B != null ? B.next : headA;
}
return A;
}
}
作者:jyd
链接:https://leetcode-cn.com/problems/intersection-of-two-linked-lists-lcci/solution/mian-shi-ti-0207-lian-biao-xiang-jiao-sh-b8hn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
8.链表:环找到了,那入口呢?
142.环形链表II
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null){
if (fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(fast == slow){
break;
}
}else {
return null;
}
}
// 此时fast在环内,接下来用面试题 02.07. 链表相交的方法找环入口
ListNode curA = head;
while (curA != slow){
curA = curA != null ? curA.next : fast;
slow = slow != null ? slow.next : head;
}
return curA;
}
}
小结
使用快慢指针,快指针走2步,慢指针走1步,使2指针在环中相遇,以相遇点作为新链表的头结点,与旧链表一起,使用上一题(面试题 02.07. 链表相交)的方法求环入口。
核心代码
链表使用快慢指针
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while (fast != null){
if (fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(fast == slow){
break;
}
}else {
return null;
}
}
}
}