- 链表逆序-已知链表头节点head,将链表逆序
/***
* 链表逆序 已知链表头节点head,将链表逆序
* @param head
* @return
*/
private static ListNode reverseList(ListNode head){
ListNode new_head = null;
while(head != null){
ListNode next = head.next; //备份head.next
head.next = new_head; //更新head.next
new_head = head; //移动new_head
head = next; //遍历链表
}
return new_head;
}
- 链表逆序,已知链表头节点,将链表从位置m到n逆序
/***
* 链表逆序,已知链表头节点,将链表从位置m到n逆序
* @param head
* @param m
* @param n
* @return
*/
private static ListNode reverseBetween(ListNode head, int m, int n){
int change_len = n - m + 1;//计算需要逆置的节点个数
ListNode pre_head = null; //初始化开始逆置的节点的前驱
ListNode result = head; //最终转换后的链表头节点,非特殊情况即为head
while(head != null && --m > 0){ //将head向前移动m-1个位置
pre_head = head;
head = head.next;
}
ListNode modify_list_tail = head; //将modify_list_tail指向当前head,即逆置后的链表尾
ListNode new_head = null;
while(head != null && change_len > 0){ //逆置change_len个节点
ListNode next = head.next;
head.next = new_head;
new_head = head;
head = next;
change_len--;
}
modify_list_tail.next = head; //连接逆置后的链表与逆置端的最后一个节点
if(pre_head != null){ //如果pre_head不为空,说明不是从第一个节点开始逆置的 m > 1
pre_head.next = new_head; //将逆置链表开始的节点前驱与逆置后的节点链接
}else{
result = new_head; //如果pre_head为空,说明m==1从第一个节点开始逆置,结果即为逆置后的链表
}
return result;
}
- 求两个链表的交点
/***
* 求两个链表的交点
* @param headA
* @param headB
* @return
*/
private static ListNode getIntersectionNode(ListNode headA, ListNode headB){
Set<ListNode> nodeSet = new HashSet<>();
while(headA != null){
nodeSet.add(headA);
headA = headA.next;
}
while(headB != null){
if(nodeSet.contains(headB)){
return headB;
}
headB = headB.next;
}
return null;
}
- 链表求环
/***
* 链表求环
* @param head
* @return
*/
private static ListNode detectCycle(ListNode head){
Set<ListNode> nodeSet = new HashSet<>();
while(head != null){
if(nodeSet.contains(head)){
return head;
}
nodeSet.add(head);
head = head.next;
}
return null;
}
- 链表的划分
/***
* 链表的划分,已知链表头指针heady与数值x, 将所有小于x的节点放在大于xde jiedian qian m
* 并且保持这些节点的原来的相对位置。
* @param head
* @param x
* @return
*/
private static ListNode partition(ListNode head, int x){
ListNode less_ptr = new ListNode(); //对应指针指向这两个头节点
ListNode more_ptr = new ListNode();
ListNode less_head = less_ptr; //设置两个临时的头节点
ListNode more_head = more_ptr;
while(head != null){
if(head.val < x){ //如果节点值小于x,则将该节点放入less_ptr之后
less_ptr.next = head;
less_ptr = head; //链接完成后,less_ptr向后移动,指向head
}else{ //否则将该节点放入more_ptr后
more_ptr.next = head;
more_ptr = head;
}
head = head.next;
}
less_ptr.next = more_head.next; //将less链表尾与more链表头相连
more_ptr.next = null; //将链表尾部节点next置空
return less_head.next;
}
- 链表合并(2个链表)
/***
* 已知两个已排序链表头节点指针l1,l2,将这两个链表合并,合并后仍为有序的,返回合并后的头节点
* @param l1
* @param l2
* @return
*/
private static ListNode mergeTwoSortedList(ListNode l1, ListNode l2){
ListNode pre = new ListNode();
ListNode head = pre;
head.next = pre;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
pre.next = l1;
l1 = l1.next; //移动l1
}else{
pre.next = l2;
l2 = l2.next; //移动l2
}
pre = pre.next; //pre指向新连接的节点
}
if(l1 != null){ //l1有元素剩余
pre.next = l1;
}
if(l2 != null){ //l2有元素剩余
pre.next = l2;
}
return head.next;
}
- 链表合并(多个链表)
/***
* 合并已排序的链表(多个)
* @param listK
* @return
*/
private static ListNode mergeKList(List<ListNode> listK){
if(listK == null || listK.size() == 0){
return null;
}
if(listK.size() == 1){
return listK.get(0);
}
if(listK.size() == 2){
return mergeTwoSortedList(listK.get(0), listK.get(1));
}
int mid = listK.size() / 2;
List<ListNode> sub1List = new ArrayList<>();
List<ListNode> sub2List = new ArrayList<>();
for(int i = 0; i < mid; i++){ //拆分listK为两个子lists
sub1List.add(listK.get(i));
}
for(int i = mid; i < listK.size(); i++){
sub2List.add(listK.get(i));
}
ListNode list1 = mergeKList(sub1List);
ListNode list2 = mergeKList(sub2List);
return mergeTwoSortedList(list1, list2);
}