[左神面试指南] 链表[下]篇
CDxxx 两个单链表相交的一系列问题⭐
-
剑指offer 链表篇 JZ52 两个链表的第一个公共结点
-
剑指offer 链表篇 JZ23 链表中环的入口结点
public Node getIntersectNode(Node head1, Node head2) {
if (head1 == null || head2 == null)
return null;
Node loop1 = getLoopNode(head1); // 判断是否有环
Node loop2 = getLoopNode(head2); // 判断是否有环
if (loop1 == null && loop2 == null) // 都没有环,判断是否相交
return noLoop(head1, head2);
if (loop1 != null && loop2 != null) // 都有环,判断是否相交
return bothLoop(head1, loop1, head2, loop2);
return null;
}
CD119 将单链表的每 K 个节点之间逆序
/* 模拟 */
public class CD119_1
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head, int K)
{
ListNode fakeHead = new ListNode(-1), pre = fakeHead, tail = head, temp, front;
int cnt = 1;
fakeHead.next = head;
while (tail != null)
{
if (cnt == K)
{
temp = tail.next;
tail.next = null;
front = pre.next;
reverseList(pre.next);
pre.next.next = temp;
pre.next = tail;
pre = front;
tail = temp;
cnt = 1;
}
cnt++;
if (tail != null)
tail = tail.next;
}
return fakeHead.next;
}
public static void reverseList(ListNode head)
{
ListNode tail = head.next, temp;
head.next = null;
while (tail != null)
{
temp = tail.next;
tail.next = head;
head = tail;
tail = temp;
}
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N, K;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
K = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l)[0], K);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
/* 栈 */
public class CD119_2
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head, int K)
{
ListNode fakeHead = new ListNode(-1), pre = fakeHead, tail = head, temp;
fakeHead.next = head;
int cnt = 1;
while (tail != null)
{
if (cnt == K)
{
temp = tail.next;
ListNode[] listNodes = reverseList(pre.next, tail);
pre.next = listNodes[0];
listNodes[1].next = temp;
pre = listNodes[1];
tail = temp;
cnt = 1;
}
cnt++;
if (tail != null)
tail = tail.next;
}
return fakeHead.next;
}
public static ListNode[] reverseList(ListNode head, ListNode tail)
{
ListNode res = null, temp = null;
Stack<ListNode> stack = new Stack<>();
while (head != tail)
{
stack.add(head);
head = head.next;
}
stack.add(tail);
while (!stack.isEmpty())
{
ListNode popNode = stack.pop();
if (res == null)
res = temp = popNode;
else
{
temp.next = popNode;
temp = temp.next;
}
}
return new ListNode[]{res, temp};
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N, K;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
K = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l)[0], K);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
CD137 删除无序单链表中值重复出现的节点
/* 模拟(超时,看思路即可) */
public class CD137_1
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head)
{
ListNode node = head, cur, pre;
while (node != null)
{
pre = node;
cur = node.next;
while (cur != null)
{
if (cur.val == node.val)
{
pre.next = cur.next;
cur.next = null;
cur = pre.next;
continue;
}
cur = cur.next;
pre = pre.next;
}
node = node.next;
}
return head;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l)[0]);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
/* 哈希 */
public class CD137_2
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head)
{
ListNode fakeHead = new ListNode(-1), tail = fakeHead;
HashMap<Integer, ListNode> map = new HashMap<>();
while (head != null)
{
if (!map.containsKey(head.val))
{
map.put(head.val, head);
tail.next = head;
tail = tail.next;
}
head = head.next;
}
tail.next = null;
return fakeHead.next;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l)[0]);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
CD138 在单链表中删除指定值的节点
/* 模拟 */
public class CD138_1
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head, int NUM)
{
ListNode fakeHead = new ListNode(-1), cur = head, pre = fakeHead;
fakeHead.next = head;
while (cur != null)
{
if (cur.val == NUM)
{
pre.next = cur.next;
cur.next = null;
cur = pre.next;
continue;
}
pre = pre.next;
cur = cur.next;
}
return fakeHead.next;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N, NUM;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
NUM = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l)[0], NUM);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
CD156 将搜索二叉树转换成双向链表⭐
/* 队列 */
public class CD156_1
{
public static class DoubleListNode
{
public int val;
public DoubleListNode prev = null;
public DoubleListNode next = null;
public DoubleListNode(int val)
{
this.val = val;
}
}
public static class TreeNode
{
public int val;
public TreeNode left = null;
public TreeNode right = null;
public TreeNode(int val)
{
this.val = val;
}
public static TreeNode createTree(int[][] nums)
{
TreeNode[] tree = new TreeNode[nums.length + 1];
Arrays.setAll(tree, TreeNode::new);
for (int i = 0; i < nums.length; i++)
{
if (nums[i][1] != 0)
tree[nums[i][0]].left = tree[nums[i][1]];
if (nums[i][2] != 0)
tree[nums[i][0]].right = tree[nums[i][2]];
}
return tree[nums[0][0]];
}
}
public static DoubleListNode solution(TreeNode root)
{
Queue<TreeNode> que = new LinkedList<>();
DoubleListNode fakeHead = new DoubleListNode(-1), tail = fakeHead;
inOrder(root, que);
while (!que.isEmpty())
{
TreeNode pollNode = que.poll();
DoubleListNode temp = new DoubleListNode(pollNode.val);
tail.next = temp;
temp.prev = tail;
tail = temp;
}
fakeHead.next.prev = null;
return fakeHead.next;
}
public static void inOrder(TreeNode root, Queue<TreeNode> que)
{
if (root == null) return;
inOrder(root.left, que);
que.add(root);
inOrder(root.right, que);
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N;
N = in.nextInt();
int[][] arr = new int[N][3];
for (int i = 0; i < N; i++)
for (int j = 0; j < 3; j++)
arr[i][j] = in.nextInt();
DoubleListNode res = solution(TreeNode.createTree(arr));
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
/* ⭐递归⭐ */
public class CD156_2
{
public static class DoubleListNode
{
public int val;
public DoubleListNode prev = null;
public DoubleListNode next = null;
public DoubleListNode(int val)
{
this.val = val;
}
}
public static class TreeNode
{
public int val;
public TreeNode left = null;
public TreeNode right = null;
public TreeNode(int val)
{
this.val = val;
}
public static TreeNode createTree(int[][] nums)
{
TreeNode[] tree = new TreeNode[nums.length + 1];
Arrays.setAll(tree, TreeNode::new);
for (int i = 0; i < nums.length; i++)
{
if (nums[i][1] != 0)
tree[nums[i][0]].left = tree[nums[i][1]];
if (nums[i][2] != 0)
tree[nums[i][0]].right = tree[nums[i][2]];
}
return tree[nums[0][0]];
}
}
public static DoubleListNode solution(TreeNode root)
{
return inOrder(root)[0];
}
public static DoubleListNode[] inOrder(TreeNode root)
{
if (root == null) return new DoubleListNode[]{null, null};
DoubleListNode temp = new DoubleListNode(root.val);
DoubleListNode left[] = inOrder(root.left);
DoubleListNode right[] = inOrder(root.right);
if (left[1] != null)
left[1].next = temp;
temp.prev = left[1];
if (right[0] != null)
right[0].prev = temp;
temp.next = right[0];
return new DoubleListNode[]{left[0] == null ? temp : left[0], right[1] == null ? temp : right[1]};
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N;
N = in.nextInt();
int[][] arr = new int[N][3];
for (int i = 0; i < N; i++)
for (int j = 0; j < 3; j++)
arr[i][j] = in.nextInt();
DoubleListNode res = solution(TreeNode.createTree(arr));
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
CD139 单链表的选择排序
/* 模拟 */
public class CD139_1
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head)
{
ListNode fakeHead = new ListNode(-1), pre, cur, temp, tempPre;
fakeHead.next = head;
head = fakeHead;
int mmin;
while (head != null)
{
tempPre = pre = head;
temp = cur = head.next;
mmin = Integer.MAX_VALUE;
while (cur != null)
{
if (cur.val < mmin)
{
mmin = cur.val;
temp = cur;
tempPre = pre;
}
cur = cur.next;
pre = pre.next;
}
if (temp != null)
{
tempPre.next = temp.next;
temp.next = head.next;
head.next = temp;
}
head = head.next;
}
return fakeHead.next;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l)[0]);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
CD157 一种怪异的节点删除方式
/* 模拟 */
public class CD157_1
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static void solution(ListNode head)
{
while (head != null && head.next != null)
{
head.val = head.next.val;
if (head.next.next == null)
head.next = null;
head = head.next;
}
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N, M;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
M = in.nextInt();
ListNode res = ListNode.createSingleList(l)[0], temp = res;
while (--M > 0)
temp = temp.next;
solution(temp);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
CD158 向有序的环形单链表中插入新节点
/* 模拟 */
public class CD158_1
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
tail.next = head.next;
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head, int NUM)
{
ListNode cur = head.next, pre = head, tail = head;
while (tail.next != head)
tail = tail.next;
if (NUM <= head.val)
{
ListNode newNode = new ListNode(NUM);
newNode.next = head;
tail.next = newNode;
head = newNode;
}
else if (NUM >= tail.val)
{
ListNode newNode = new ListNode(NUM);
tail.next = newNode;
newNode.next = head;
}
else
{
while (cur != null)
{
if (pre.val <= NUM && NUM <= cur.val)
{
ListNode newNode = new ListNode(NUM);
pre.next = newNode;
newNode.next = cur;
break;
}
pre = pre.next;
cur = cur.next;
}
}
return head;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N, NUM;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
NUM = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l)[0], NUM), head = res;
while (res.next != head)
{
out.print(res.val + " ");
res = res.next;
}
out.println(res.val);
out.flush();
}
}
CD159 合并两个有序的单链表
/* 归并 */
public class CD159_1
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head1, ListNode head2)
{
ListNode fakeHead = new ListNode(-1), cur = fakeHead;
while (head1 != null && head2 != null)
{
if (head1.val <= head2.val)
{
cur.next = head1;
cur = cur.next;
head1 = head1.next;
}
else
{
cur.next = head2;
cur = cur.next;
head2 = head2.next;
}
}
cur.next = (head1 == null ? head2 : head1);
return fakeHead.next;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N, M;
N = in.nextInt();
int[] l1 = new int[N];
for (int i = 0; i < N; i++)
l1[i] = in.nextInt();
M = in.nextInt();
int[] l2 = new int[M];
for (int i = 0; i < M; i++)
l2[i] = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l1)[0], ListNode.createSingleList(l2)[0]);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}
CD160 按照左右半区的方式重新组合单链表
/* 模拟 */
public class CD160_1
{
public static class ListNode
{
public int val;
public ListNode next = null;
public ListNode(int val)
{
this.val = val;
}
public static ListNode[] createSingleList(int[] nums)
{
ListNode head = new ListNode(-1), tail = head;
for (int num : nums)
{
tail.next = new ListNode(num);
tail = tail.next;
}
return new ListNode[]{head.next, tail};
}
}
public static ListNode solution(ListNode head)
{
ListNode fakeHead = new ListNode(-1), pre = fakeHead, fast = head, slow = head, tail = fakeHead;
fakeHead.next = head;
boolean flag = true;
while (fast != null && fast.next != null)
{
pre = pre.next;
slow = slow.next;
fast = fast.next.next;
}
pre.next = null;
while (head != null && slow != null)
{
if (flag)
{
tail.next = head;
tail = tail.next;
head = head.next;
}
else
{
tail.next = slow;
tail = tail.next;
slow = slow.next;
}
flag = !flag;
}
tail.next = (head == null) ? slow : head;
return fakeHead.next;
}
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
PrintWriter out = new PrintWriter(System.out);
int N;
N = in.nextInt();
int[] l = new int[N];
for (int i = 0; i < N; i++)
l[i] = in.nextInt();
ListNode res = solution(ListNode.createSingleList(l)[0]);
while (res != null)
{
out.print(res.val + (res.next == null ? "" : " "));
res = res.next;
}
out.flush();
}
}