版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32768743/article/details/81948196
- 基本的插入、删除、遍历操作
- 实现栈
- 找倒数第n个节点
双指针实现
- 扩展1:找两个链表的合并节点
扩展2:从表尾开始找模结点
判环
快慢指针实现(Floyd环判定算法)
- 扩展1:求环长
- 扩展2:找中间节点
- 反转链表
- 扩展1:逐对反转
- 扩展2:每K个节点反转
- 约瑟夫环
- 复制链表(节点含兄弟指针)
散列表辅助
附:
public class ListNode {
private int data;
private ListNode next;
public ListNode(int data) {
this.data = data;
}
public ListNode(int data, ListNode next) {
this.data = data;
this.next = next;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public ListNode getNext() {
return next;
}
public void setNext(ListNode next) {
this.next = next;
}
@Override
public String toString() {
ListNode head = this;
ListNode it = this;
StringBuilder msg = new StringBuilder();
while (it != null) {
msg.append(it.data);
if (it.next != null && it.next != head && it.next != it) {
msg.append("->");
}
it = it.next;
if (it == head) break;
}
return msg.toString();
}
public static int listLength(ListNode headNode) {
int length = 0;
ListNode currentNode = headNode;
while (currentNode != null) {
length++;
currentNode = currentNode.next;
}
return length;
}
public static ListNode insertInLinkedList(ListNode headNode, ListNode nodeToInsert, int position) {
if (headNode == null) return nodeToInsert;
int size = listLength(headNode);
if (position > size + 1 || position < 1) {
System.out.println("Position of node to insert is invalid. The valid inputs are 1 to " + (size + 1));
return headNode;
}
if (position == 1) {
nodeToInsert.next = headNode;
return nodeToInsert;
}
ListNode previousNode = headNode;
int count = 1;
while (count < position) {
previousNode = previousNode.next;
count++;
}
ListNode currentNode = previousNode.next;
nodeToInsert.next = currentNode;
previousNode.next = nodeToInsert;
return headNode;
}
public static ListNode deleteNodeFromLinkedList(ListNode headNode, int position) {
int size = listLength(headNode);
if (position > size || position < 1) {
System.out.println("Position of node to delete is invalid. The valid inputs are 1 to " + size);
return headNode;
}
if (position == 1) {
ListNode currentNode = headNode.next;
headNode = null;
return currentNode;
}
ListNode previousNode = headNode;
int count = 1;
while (count < position) {
previousNode = previousNode.next;
count++;
}
ListNode currentNode = previousNode.next;
previousNode.next = currentNode.next;
currentNode = null;
return headNode;
}
public static void deleteLinkdedList(ListNode head) {
ListNode auxilaryNode, iterator = head;
while (iterator != null) {
auxilaryNode = iterator.next;
iterator = null;
iterator = auxilaryNode;
}
}
public static ListNode nthNodeFromEnd(ListNode head, int nthNode) {
if (head == null) return null;
if (nthNode <= 0) return null;
ListNode node = head, prev = null;
for (int count = 1; count < nthNode; count++) {
if (node != null) node = node.next;
}
while (node != null) {
prev = (prev == null) ? head : prev.next;
node = node.next;
}
return node;
}
public static boolean doesLinkedListContainsLoop(ListNode head) {
if (head == null) return false;
ListNode fastNode = head, slowNode = head;
while (fastNode.next != null && fastNode.next.next != null) {
fastNode = fastNode.next.next;
slowNode = slowNode.next;
if (fastNode == slowNode) {
return true;
}
}
return false;
}
public static ListNode reverseList(ListNode head) {
ListNode temp = null, nextNode = null;
while (head != null) {
nextNode = head.next;
head.next = temp;
temp = head;
head = nextNode;
}
return temp;
}
public static ListNode findIntersectingNode(ListNode list1, ListNode list2) {
if (list1 == null || list2 == null) {
return null;
}
int count1 = 0, count2 = 0;
ListNode it = list1;
while (it != null) {
count1++;
it = it.next;
}
it = list2;
while (it != null) {
count2++;
it = it.next;
}
ListNode head1 = list1, head2 = list2;
int diffCount = count1 - count2;
if (count1 < count2) {
head1 = list2;
head2 = list1;
diffCount = count2 - count1;
}
for (int i = 0; i < diffCount; i++) {
head1 = head1.next;
}
while (head1 != null && head2 != null) {
if (head1 == head2) return head1;
head1 = head1.next;
head2 = head2.next;
}
return null;
}
public static ListNode findMiddle(ListNode head) {
if (head == null) return null;
ListNode slowNode = head, fastNode = head;
while (fastNode.next != null && fastNode.next.next != null) {
slowNode = slowNode.next;
fastNode = fastNode.next.next;
}
return slowNode;
}
public static void printListFromEnd(ListNode head) {
if (head == null) return;
printListFromEnd(head.next);
System.out.print(head.data + " ");
}
public static boolean isLinkedListLengthEven(ListNode listHead) {
while (listHead != null && listHead.next != null) {
listHead = listHead.next.next;
}
return listHead == null;
}
public static ListNode mergeList(ListNode a, ListNode b) {
ListNode result = null;
if (a == null) return b;
if (b == null) return a;
if (a.data < b.data) {
result = a;
result.next = mergeList(a.next, b);
} else {
result = b;
result.next = mergeList(a, b.next);
}
return result;
}
public static ListNode reversePairRecursive(ListNode head) {
if (head == null || head.next == null) return head;
int temp = head.data;
head.data = head.next.data;
head.next.data = temp;
reversePairRecursive(head.next.next);
return head;
}
public static ListNode reversePairIterative(ListNode head) {
if (head == null || head.next == null) return head;
ListNode it = head;
while (it != null && it.next != null) {
int temp = it.data;
it.data = it.next.data;
it.next.data = temp;
it = it.next.next;
}
return head;
}
private static boolean hasEnoughNode(ListNode head, int k) {
if (head == null) return false;
ListNode currentNode = head;
for (int i = 0; i < k; i++) {
currentNode = currentNode.next;
if (currentNode == null) return false;
}
return true;
}
public static ListNode reverseList(ListNode head, int k) {
if (head == null) return null;
// 如果链表不足k个节点,不用反转
if (k == 1 || !hasEnoughNode(head, k)) return head;
ListNode result = null;
// 当前头节点,反转后变成尾节点
ListNode currentHead = head;
// 连接反转后的头节点
ListNode lastTail = null;
ListNode currentNode = head;
do {
// 反转这部分的链表
ListNode newHead = null;
for (int i = 0; i < k; i++) {
ListNode t = currentNode.next;
currentNode.next = newHead;
newHead = currentNode;
currentNode = t;
}
if (result == null) result = newHead;
if (lastTail != null) lastTail.next = newHead;
lastTail = currentHead;
currentHead.next = currentNode;
currentHead = currentHead.next;
} while (hasEnoughNode(currentHead, k));
return result;
}
public static int getJosephusPosition(int n, int m) {
ListNode head = new ListNode(1);
ListNode tail = head;
for (int i = 1; i < n; i++) {
tail.next = new ListNode(i + 1);
tail = tail.next;
}
tail.next = head;
ListNode it = tail;
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < m - 1; j++) it = it.next;
it.next = it.next.next;
}
return it.data;
}
public static ListNode modularNodes(ListNode head, int k) {
ListNode modularNode = null;
if(k<=0) return null;
for(int i = 1;head!=null;head=head.next){
if(i%k==0){
modularNode = head;
}
i++;
}
return modularNode;
}
public static void main(String[] args) {
ListNode next = new ListNode(3);
ListNode head = new ListNode(1, new ListNode(2, next));
next.setNext(head);
System.out.println(head.toString());
}
}
测试
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import static org.junit.Assert.*;
public class ListNodeTest {
private ListNode head;
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
@Before
public void setUp() throws Exception {
head = new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4,new ListNode(5)))));
System.setOut(new PrintStream(outContent));
System.setErr(new PrintStream(errContent));
}
@After
public void tearDown(){
System.setOut(null);
System.setErr(null);
}
@Test
public void testFindMiddle() {
ListNode result = ListNode.findMiddle(head);
Assert.assertEquals(3,result.getData());
}
@Test
public void testFindMiddle_1() {
head = new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4))));
ListNode result = ListNode.findMiddle(head);
Assert.assertEquals(2,result.getData());
}
@Test
public void testPrintListFromEnd(){
ListNode.printListFromEnd(head);
Assert.assertEquals("5 4 3 2 1 ",outContent.toString());
}
@Test
public void testIsLinkedListLengthEven(){
boolean result = ListNode.isLinkedListLengthEven(head);
Assert.assertFalse(result);
}
@Test
public void testIsLinkedListLengthEven_1(){
head = new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4))));
boolean result = ListNode.isLinkedListLengthEven(head);
Assert.assertTrue(result);
}
@Test
public void testMergeList(){
ListNode b = new ListNode(1,new ListNode(2,new ListNode(3,new ListNode(4))));
ListNode newHead = ListNode.mergeList(head,b);
print(newHead);
Assert.assertEquals("1 1 2 2 3 3 4 4 5 ",outContent.toString());
}
@Test
public void testReversePairRecursive(){
ListNode newHead = ListNode.reversePairRecursive(head);
print(newHead);
Assert.assertEquals("2 1 4 3 5 ", outContent.toString());
}
@Test
public void testReversePairRecursive_1(){
ListNode head = new ListNode(1,new ListNode(2));
ListNode newHead = ListNode.reversePairRecursive(head);
print(newHead);
Assert.assertEquals("2 1 ", outContent.toString());
}
@Test
public void testReversePairRecursive_2(){
ListNode head = new ListNode(1,new ListNode(2, new ListNode(3)));
ListNode newHead = ListNode.reversePairRecursive(head);
print(newHead);
Assert.assertEquals("2 1 3 ", outContent.toString());
}
@Test
public void testReversePairIterative(){
ListNode newHead = ListNode.reversePairIterative(head);
print(newHead);
Assert.assertEquals("2 1 4 3 5 ", outContent.toString());
}
@Test
public void testReverseBlockOfKNodesInLinkedList_1(){
ListNode newHead= ListNode.reverseList(head,1);
print(newHead);
Assert.assertEquals("1 2 3 4 5 ", outContent.toString());
}
@Test
public void testReverseBlockOfKNodesInLinkedList_2(){
ListNode newHead= ListNode.reverseList(head,2);
print(newHead);
Assert.assertEquals("2 1 4 3 5 ", outContent.toString());
}
@Test
public void testReverseBlockOfKNodesInLinkedList_3(){
head = new ListNode(3,new ListNode(4, new ListNode(5)));
ListNode newHead= ListNode.reverseList(head,2);
print(newHead);
Assert.assertEquals("4 3 5 ", outContent.toString());
}
@Test
public void testReverseBlockOfKNodesInLinkedList_4(){
ListNode newHead= ListNode.reverseList(head,3);
print(newHead);
Assert.assertEquals("3 2 1 4 5 ", outContent.toString());
}
@Test
public void testGetJosephusPosition(){
int result = ListNode.getJosephusPosition(3,2);
Assert.assertEquals(3,result);
}
@Test
public void testGetJosephusPosition_2(){
int result = ListNode.getJosephusPosition(9,4);
Assert.assertEquals(1,result);
}
@Test
public void testGetJosephusPosition_3(){
int result = ListNode.getJosephusPosition(9,1);
Assert.assertEquals(9,result);
}
@Test
public void testGetJosephusPosition_4(){
int result = ListNode.getJosephusPosition(1,10);
Assert.assertEquals(1,result);
}
@Test
public void testGetJosephusPosition_5(){
int result = ListNode.getJosephusPosition(8,5);
Assert.assertEquals(3,result);
}
@Test
public void testGetJosephusPosition_6(){
int result = ListNode.getJosephusPosition(6,6);
Assert.assertEquals(4,result);
}
@Test
public void testGetJosephusPosition_7(){
int result = ListNode.getJosephusPosition(2,1);
Assert.assertEquals(2,result);
}
@Test
public void testGetJosephusPosition_8(){
int result = ListNode.getJosephusPosition(3,1);
Assert.assertEquals(3,result);
}
private void print(ListNode head){
ListNode it = head;
while(it!=null){
System.out.print(it.getData()+" ");
it = it.getNext();
}
}
}