1. 删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点
思路 链表常用解法:双指针定位
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode pre = dummy;
ListNode cur = dummy;
while(n--!=0){
cur = cur.next;
}
while(cur.next!=null){
cur = cur.next;
pre = pre.next;
}
pre.next = pre.next.next;
return dummy.next;
}
}
2. 反转链表
迭代或递归地反转链表。你能否用两种方法解决这道题?
递归+回溯解法:
public ListNode reverseList(ListNode head) {
if(head == null || head.next==null){
return head;
}
//获得尾节点
ListNode ret = reverseList(head.next);
//下面属于回溯,从后往前继续切换
head.next.next = head;
head.next = null;
return ret;
}
迭代:
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode pre = null;
while(cur!=null){
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
递归思想还是有一定难度的,注意是进入递归前处理还是递归后处理,递归后处理(回溯)要有返回上个现场的思想,这道题需要在递归后才好处理节点转向。
3. 合并两个有序链表
思路1:循环拼接
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode pre = new ListNode(-1);
ListNode prev = pre;
while(l1!=null && l2!=null){
if(l1.val<l2.val){
prev.next = l1;
l1 = l1.next;
}else{
prev.next = l2;
l2 = l2.next;
}
prev = prev.next;
}
prev.next = l1==null?l2:l1;
return pre.next;
}
思路2:递归
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null){
return l2;
}
if(l2==null){
return l1;
}
if(l1.val<l2.val){
l1.next = mergeTwoLists(l1.next,l2);
return l1;
}else{
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
4. 是否为回文链表
时间复杂度O(n),空间复杂度o(2n)
public boolean isPalindrome(ListNode head) {
Stack<Integer> stack = new Stack<>();
Queue<Integer> que = new LinkedList<>();
while(head!=null){
que.add(head.val);
stack.add(head.val);
head = head.next;
}
while(!que.isEmpty()){
if(!que.poll().equals(stack.pop())){
return false;
}
}
return true;
}
5. 检测链表的环入口
如果链表有环,返还入口节点,否则返回null
典型的双指针问题:假设快慢指针有交点,则x+y+z+y = 2(x+y)
public ListNode detectCycle(ListNode head) {
ListNode fast = head, slow = head;
while (true) {
if (fast == null || fast.next == null) return null;
fast = fast.next.next;
slow = slow.next;
if (fast == slow) break;
}
fast = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return fast;
}