数组链表相关问题先判空
- 循环的作用:让指针或者游标动起来
- 写循环一定要想到循环什么时候截止(尽量不使用break)
- 写if-else考虑清楚什么情况下应该做什么
- 图形化写法,边画图边写,走一步写一步
class Solution {
public int removeDuplicates(int[] nums) {
int fast = 0;
int slow = 0;
if(nums.length == 0) {
return 0;
}
for (int i=0; i<nums.length; i++) {
if(nums[fast] == nums[slow]) {
fast++;
}
else {
slow++;
nums[slow] = nums[fast];
fast++;
}
}
return slow+1;
}
}
/**
* 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 deleteDuplicates(ListNode head) {
if(head == null) {
return null;
}
ListNode slow = head;
ListNode fast = head;
while (fast != null) {
if(fast.val == slow.val) {
fast = fast.next;
} else {
slow.next = fast;
slow = fast;
}
}
slow.next = null; //很重要
return head;
}
}
class Solution {
public int removeElement(int[] nums, int val) {
if(nums.length == 0) {
return 0;
}
int fast = 0;
int slow = 0;
while(fast < nums.length) {
if(nums[fast] != val) {
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
}
/**
* 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 partition(ListNode head, int x) {
if(head == null) {
return null;
}
//创建虚结点
ListNode h1 = new ListNode(-1);
ListNode h2 = new ListNode(-1);
//定义指针指向虚结点的头结点
ListNode p1 = h1;
ListNode p2 = h2;
while(head != null) {
if(head.val < x) {
p1.next = head;
p1 = p1.next;
head = head.next;
} else {
p2.next = head;
p2 = p2.next;
head = head.next;
}
}
p2.next = null;
p1.next = h2.next;
h1 = h1.next;
return h1;
}
}
19. 删除链表的倒数第 N 个结点
上述报错在于,p2.next可能为空,于是p2.next.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 removeNthFromEnd(ListNode head, int n) {
// 建立假结点防止只有一个数据的情况
ListNode d = new ListNode(-1);
d.next = head;
ListNode p1 = d;
ListNode p2 = d;
int num = n;
// 让p2先走n步
while(num != 0) {
p2 = p2.next;
num--;
}
//p1 p2同时走
while(p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
p1.next = p1.next.next;
return d.next;
}
}
876. 链表的中间结点
有一个指针走两步,先判断它是否为空,再判断它的next是否为null,否则可能产生空指针错误
/**
* 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;
}
ListNode p1 = headA;
ListNode p2 = headB;
//两者相遇时 或者 都为null时结束
while(p1 != p2) {
if(p1 == null) {
p1 = headB;
} else {
p1 = p1.next;
}
if(p2 == null) {
p2 = headA;
} else {
p2 = p2.next;
}
}
return p1;
}
}