前言
1、重排链表
2、旋转链表
3、删除排序链表中的重复元素 II
4、重复的DNA序列
一、重排链表(力扣143)
分析:
1->2->3->4->5->6
1、找中点分为两段链表 【快慢指针】
1->2->3
4->5->6
2、将第二段链表进行逆置【递归或者其他方法都可以】
1->2->3
6->5->4
3、合并两个链表
1->6->2->5->3->4
/**
* 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 void reorderList(ListNode head) {
ListNode fast=head;
ListNode slow=head;
ListNode post;
while(fast!=null && fast.next!=null){
slow = slow.next;
fast=fast.next.next;
}
//此时slow指针所指位置为中点
post = slow.next;
slow.next = null;
//将后一段链表逆序
ListNode newPost = reverse(post);
//拼接两个链表
//链表节点依次连接
ListNode s = head;
ListNode e = newPost;
while(s!=null && e!=null){
ListNode sn = s.next;
s.next = e;
ListNode en = e.next;
e.next =sn;
s=sn;
e=en;
}
}
public ListNode reverse(ListNode head){
if(head==null) return null;
if(head.next==null) return head;
ListNode last = reverse(head.next);
head.next.next = head;
head.next = null;
return last;
}
}
二、旋转链表(力扣61)
分析:
利用之前的快慢指针求倒数第n个结点 然后将第二段链表的尾巴接到第一段链表的头部即可
需要注意的细节在于 倒数第n的结点: k%链表长度 需要多加判断 当n==0时直接返回原链表即可 。
如果链表长度为0 则直接返回null即可
/**
* 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 rotateRight(ListNode head, int k) {
//判断从哪个结点开始挪动
//先计算当前链表长度
ListNode cur = head;
int length =0;
while(cur!=null){
length++;
cur=cur.next;
}
if(length==0) return null;
int n = k%length;
if(n==0) return head;
//倒数第n个结点摘到前边去
//快慢指针
ListNode slow=head;
ListNode fast=head;
//快指针先走
for(int i=0;i<n;i++){
fast = fast.next;
}
while(fast.next!=null){ //找到了倒数第n个指针的前一个指针slow
fast = fast.next;
slow = slow.next;
}
ListNode newHead = slow.next;
slow.next=null;
cur = newHead;
while(cur.next!=null){
cur=cur.next;
}
cur.next = head;
return newHead;
}
}
三、删除排序链表中的重复元素 II(力扣82)
分析:
要删除所有相同的结点 可能会将第一个节点删除,那么此时就需要虚拟头节点方便操作。
将cur.next.val记录下来,然后和cur.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 deleteDuplicates(ListNode head) {
if(head==null) return null;
if(head.next==null) return head;
//需要引入头节点
ListNode dummy = new ListNode(-1,head);
ListNode cur = dummy;
while(cur.next!=null && cur.next.next!=null){
int value = cur.next.val;
if(cur.next.next.val==value){
//开始删除节点
while(cur.next!=null && cur.next.val==value){
cur.next = cur.next.next;
}
}else{
cur = cur.next;
}
}
return dummy.next;
}
}
四、重复的DNA序列(力扣187)【滑动窗口】
class Solution {
public List<String> findRepeatedDnaSequences(String s) {
int left = 0;
int right = 9;
HashMap<String,Integer> map = new HashMap<>();
List<String> res = new ArrayList<>();
while(right<s.length()){
//移动滑窗
while(right-left+1==10 && right<s.length()){
String sub = s.substring(left,right+1);
if(map.containsKey(sub) && map.get(sub)<=1){
res.add(sub);
}
map.put(sub,map.getOrDefault(sub,0)+1);
right++;
left++;
}
}
return res;
}
}