連結串列(2)——中等難度
技術標籤:牛客演算法篇-高頻TOP200連結串列java演算法
連結串列—中等難度(java實現)
連結串列中環的入口節點
題目描述
對於一個給定的連結串列,返回環的入口節點,如果沒有環,返回null
拓展:
你能給出不利用額外空間的解法麼?
(圖源牛客LPL006題解)
/**
* 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;
//設在進入環前路程為a,二指標在距環起點為b位置相遇,環總長(b+c)
//即慢指標行 a+b , 快指標行a+b+n(b+c)
//快指標速度為慢指標2倍,則 2*(a+b)=a+b+n*(b+c)
//推出 a = (n-1)(b+c) + c
//此時將速度相同的兩個指標分別放在開頭和環相遇位置,二者相遇在環起點
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
ListNode tmp = head;
while(tmp != slow){
tmp = tmp.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
}
刪除連結串列的倒數第n個節點
題目描述
給定一個連結串列,刪除連結串列的倒數第n個節點並返回連結串列的頭指標
例如,
給出的連結串列為:1->2->3->4->5, n= 2.
刪除了連結串列的倒數第n個節點之後,連結串列變為1->2->3->5.
備註:
題目保證n一定是有效的
請給出請給出時間複雜度為\ O(n) O(n)的演算法
題目已知給出的n一定是有效的,所以無需再考慮n小於0或者大於連結串列長度的情況
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode類
* @param n int整型
* @return ListNode類
*/
public ListNode removeNthFromEnd (ListNode head, int n) {
// write code here
ListNode fast = head;
ListNode slow = head;
for(int i = 0; i < n; i++)
fast = fast.next;
//若n等於連結串列的長度,則直接返回去掉頭結點的連結串列
if(fast == null)
return head.next;
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
//1 2 3 4 5 6 7
slow.next = slow.next.next;
return head;
}
}
刪除有序連結串列中重複出現的元素
題目描述
給出一個升序排序的連結串列,刪除連結串列中的所有重複出現的元素,只保留原連結串列中只出現一次的元素。
例如:
給出的連結串列為1→2→3→3→4→4→5, 返回1→2→5.
給出的連結串列為1→1→1→2→3, 返回2→3.
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode類
* @return ListNode類
*/
public ListNode deleteDuplicates (ListNode head) {
// write code here
ListNode res = new ListNode(0);
res.next = head;
ListNode pre = res;
ListNode cur = head;
while(cur != null && cur.next != null){
if(cur.val != cur.next.val)
pre = cur;
else{
while(cur.next != null && cur.val == cur.next.val)
cur = cur.next;
pre.next = cur.next;
}
cur = cur.next;
}
return res.next;
}
}
連結串列的奇偶重排
題目描述
給定一個單鏈表,請設定一個函式,講連結串列的奇數位節點和偶數位節點分別放在一起,重排後輸出。
注意是節點的編號而非節點的數值。
示例1
輸入:{1,2,3,4,5,6}
返回值:{1,3,5,2,4,6}
示例2
輸入:{1,4,6,3,7}
返回值:{1,6,7,4,3}
說明:奇數節點有1,6,7,偶數節點有4,3。重排後為1,6,7,4,3
備註:連結串列長度不大於200000。每個數範圍均在int內。
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
* 程式碼中的類名、方法名、引數名已經指定,請勿修改,直接返回方法規定的值即可
*
* @param head ListNode類
* @return ListNode類
*/
public ListNode oddEvenList (ListNode head) {
// write code here
if(head == null || head.next == null)
return head;
ListNode evenhead = head.next;
ListNode odd = head;
ListNode even = head.next;
int i = 1;
while(even != null && even.next != null){
odd.next = even.next;
odd = odd.next;
even.next = odd.next;
even = even.next;
}
//奇數鏈與偶數鏈相連
odd.next = evenhead;
return head;
}
}
劃分連結串列
題目描述
給出一個連結串列和一個值 ,以 為參照將連結串列劃分成兩部分,使所有小於 的節點都位於大於或等於 的節點之前。
兩個部分之內的節點之間要保持的原始相對順序。
例如:
給出1→4→3→2→5→2 和x=3,
返回 1→2→2→4→3→5.
示例1
輸入:{1,4,3,2,5,2},3
返回值:{1,2,2,4,3,5}
import java.util.*;
/*
* public class ListNode {
* int val;
* ListNode next = null;
* }
*/
public class Solution {
/**
*
* @param head ListNode類
* @param x int整型
* @return ListNode類
*/
public ListNode partition (ListNode head, int x) {
// write code here
if(head == null)
return null;
ListNode res1 = new ListNode(0);
ListNode res2 = new ListNode(0);
ListNode left = res1;
ListNode right = res2;
while(head != null){
if(head.val < x){
left.next = head;
left = left.next;
}
else{
right.next = head;
right = right.next;
}
head =head.next;
}
right.next = null;
left.next = res2.next;
return res1.next;
}
}