最近在复习数据结构,做了一些数据结构方面的笔试编程题,代码总结如下:
ps:下面的单链表默认都没有傀儡节点。
1、删除链表中等于给定值 val 的所有节点
1 public ListNode removeElements(ListNode head, int val) {
2 ListNode newhead = head;
3 while (newhead != null && newhead.val == val) {
4 newhead = newhead.next;
5 }
6 if (newhead == null)
7 return null;
8 ListNode front = newhead;
9 ListNode last = newhead.next;
10 while (last != null) {
11 if (last.val == val) {
12 front.next = last.next;
13 last = last.next;
14 } else {
15 front = last;
16 last = last.next;
17 }
18 }
19 return newhead;
20 }
2、反转一个单链表
1 public ListNode reverseList(ListNode head) {
2 if (head == null) {
3 return null;
4 }
5 ListNode newHead = head;
6 ListNode tmp = head.next;
7 head.next = null;
8 while (tmp != null) {
9 ListNode temp = tmp;
10 tmp = tmp.next;
11 temp.next = newHead;
12 newHead = temp;
13 }
14 return newHead;
15 }
3、求链表的中间节点
1 public ListNode middleNode(ListNode head) {
2 if (head == null) {
3 return null;
4 }
5 if (head.next == null) {
6 return head;
7 }
8 int length = 0;
9 ListNode tmp = head;
10 while (tmp != null) {
11 length++;
12 tmp = tmp.next;
13 }
14 tmp = head;
15 for (int i = 0; i < length / 2; i++) {
16 tmp = tmp.next;
17 }
18 return tmp;
19 }
4、求倒数第k个链表
1 public ListNode FindKthToTail(ListNode head, int k) {
2 if (k == 0) {
3 return null;
4 }
5 ListNode front = head;
6 ListNode last = head;
7 while (--k > 0 && last != null) {
8 last = last.next;
9 }
10 if (last == null) {
11 return null;
12 }
13 if (last.next == null && k == 0) {
14 return head;
15 }
16
17 while (last.next != null) {
18 front = front.next;
19 last = last.next;
20 }
21 return front;
22 }
5、分割链表
1 public ListNode partition(ListNode pHead, int x) {
2 if (pHead == null) {
3 return null;
4 }
5 ListNode newHead = null;
6 ListNode tmp = pHead;
7 ListNode temp = newHead;
8 while (pHead != null) {
9 if (pHead.val < x) {
10 if (newHead == null) {
11 newHead = pHead;
12 temp = newHead;
13 } else {
14 temp.next = pHead;
15 temp = temp.next;
16 }
17 pHead = pHead.next;
18 temp.next = null;
19 } else {
20 break;
21 }
22 }
23 if (pHead == null) {
24 return newHead;
25 }
26
27 if (newHead == null) {
28 while (tmp.next != null && tmp.next.val >= x) {
29 tmp = tmp.next;
30 }
31 if (tmp.next == null) {
32 return pHead;
33 }
34 newHead = tmp.next;
35 tmp.next = tmp.next.next;
36 temp = newHead;
37 temp.next = null;
38 }
39
40 tmp = pHead;
41 while (tmp.next != null) {
42 while (tmp.next != null && tmp.next.val >= x) {
43 tmp = tmp.next;
44 }
45 if (tmp.next == null) {
46 temp.next = pHead;
47 } else {
48 temp.next = tmp.next;
49 temp = temp.next;
50 tmp.next = tmp.next.next;
51 temp.next = null;
52 }
53 }
54
55 temp.next = pHead;
56 return newHead;
57 }
6、去除链表重复节点,即1122234变成34
1 public ListNode deleteDuplication(ListNode pHead) {
2 if (pHead == null) {
3 return null;
4 }
5 // 去除开头重复节点
6 while (pHead.next != null && pHead.val == pHead.next.val) {
7 int tmp = pHead.val;
8 while (pHead != null && pHead.val == tmp) {
9 pHead = pHead.next;
10 }
11 if (pHead == null) {
12 return null;
13 }
14 }
15 if (pHead.next == null) {
16 return pHead;
17 }
18 // 去除中间重复节点
19 boolean is = false;
20 ListNode node = pHead;
21 while (node.next != null) {
22 ListNode temp = node.next;
23 int tmp = temp.val;
24 while (temp.next != null && temp.next.val == temp.val) {
25 temp.next = temp.next.next;
26 is = true;
27 }
28 if (is) {
29 node.next = temp.next;
30 is = false;
31 } else {
32 node = node.next;
33 }
34 }
35 return pHead;
36 }
7、判断链表的回文结构
1 public boolean chkPalindrome(ListNode A) {
2 ArrayList<Integer> list = new ArrayList<>();
3 ListNode cur = A;
4 while (cur != null) {
5 list.add(cur.val);
6 cur = cur.next;
7 }
8 int length = list.size();
9 int left = 0;
10 int right = length - 1;
11 while (left < right) {
12 if (!list.get(left).equals(list.get(right))) {
13 return false;
14 }
15 left++;
16 right--;
17 }
18 return true;
19 }
8、判断两个链表是否有交点,并返回第一个交点
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lengthA = 0;
int lengthB = 0;
ListNode tmpA = headA;
ListNode tmpB = headB;
while (tmpA != null) {
lengthA++;
tmpA = tmpA.next;
}
while (tmpB != null) {
lengthB++;
tmpB = tmpB.next;
}
tmpA = headA;
tmpB = headB;
if (lengthA > lengthB) {
for (int i = 0; i < lengthA - lengthB; i++) {
tmpA = tmpA.next;
}
} else {
for (int i = 0; i < lengthB - lengthA; i++) {
tmpB = tmpB.next;
}
}
while (tmpA != null) {
if (tmpA == tmpB) {
return tmpA;
}
tmpA = tmpA.next;
tmpB = tmpB.next;
}
return null;
}
9、判断链表是否有环
1 public boolean hasCycle(ListNode head) {
2 ListNode slow = head;
3 ListNode fast = head;
4 while (fast != null && fast.next != null) {
5 fast = fast.next.next;
6 slow = slow.next;
7 if (fast == slow) {
8 return true;
9 }
10 }
11 return false;
12 }
10、找链表的入环节点
1 public ListNode detectCycle(ListNode head) {
2 // 判断是否有环
3 ListNode slow = head;
4 ListNode fast = head;
5 while (fast != null && fast.next != null) {
6 slow = slow.next;
7 fast = fast.next.next;
8 if (fast == slow) {
9 break;
10 }
11 }
12 if (fast == null || fast.next == null) {
13 return null;
14 }
15 // 找入环结点
16 slow = head;
17 while (slow != fast) {
18 slow = slow.next;
19 fast = fast.next;
20 }
21 return slow;
22 }
11、删除倒数第n个节点
1 public ListNode removeNthFromEnd(ListNode head, int n) {
2 ListNode fast = head;
3 ListNode slow = head;
4 int i = 0;
5 for (; i < n && fast != null; i++) {
6 fast = fast.next;
7 }
8 if (i == n) {
9 if (fast == null) {
10 head = head.next;
11 return head;
12 } else {
13 while (fast.next != null) {
14 slow = slow.next;
15 fast = fast.next;
16 }
17 slow.next = slow.next.next;
18 return head;
19 }
20 }
21 return head;
22 }
12、合并k个有序链表
1 public ListNode mergeKLists(ListNode[] lists) {
2 int size = lists.length;
3 if (size == 0) {
4 return null;
5 }
6 if (size == 1) {
7 return lists[0];
8 }
9 ListNode tt = lists[0];
10 for (int i = 1; i < size; i++) {
11 ListNode tmp = lists[i];
12 tt = lists[0];
13 // 合并两个链表
14 if (tt == null) {
15 lists[0] = tmp;
16 continue;
17 }
18 if (tmp == null) {
19 continue;
20 }
21 // 判断第一个结点的大小
22 if (tmp.val < lists[0].val) {
23 lists[0] = tmp;
24 tmp = tmp.next;
25 lists[0].next = tt;
26 tt = lists[0];
27 }
28 while (tt.next != null && tmp != null) {
29 if (tt.next.val >= tmp.val) { // 插入tmp
30 ListNode t = tmp.next;
31 tmp.next = tt.next;
32 tt.next = tmp;
33 tmp = t;
34 tt = tt.next;
35 } else {
36 tt = tt.next;
37 }
38 }
39 if (tt.next == null) {
40 tt.next = tmp;
41 }
42 }
43 return lists[0];
44 }
13、两两交换链表中的节点
1 public ListNode swapPairs(ListNode head) {
2 if (head == null) {
3 return null;
4 }
5 if (head.next == null) {
6 return head;
7 }
8 ListNode tmp = head; // 1
9 ListNode front = head; // 1
10 head = head.next; // 2
11 tmp.next = head.next;// 1->3
12 head.next = tmp;// 2->1
13 tmp = front.next;// 3
14 while (tmp != null && tmp.next != null) {
15 ListNode t = tmp.next.next;// null
16 front.next = tmp.next;
17 tmp.next.next = tmp;
18 tmp.next = t;
19 front = tmp;
20 tmp = t;
21 }
22 return head;
23 }
14、旋转链表,顺时针旋转k个位置,即12345,旋转2个位置后变成45123
1 public ListNode rotateRight(ListNode head, int k) {
2 if (head == null) {
3 return null;
4 }
5 if (head.next == null) {
6 return head;
7 }
8 int length = 0;
9 ListNode fast = head;
10 ListNode slow = head;
11 // 计算链表长度
12 while (fast != null) {
13 fast = fast.next;
14 length++;
15 }
16 int len = k % length; // 旋转长度
17 if (len == 0) {
18 return head;
19 }
20 fast = head;
21 for (int i = 0; i < len; i++) {
22 fast = fast.next;
23 }
24 while (fast.next != null) {
25 slow = slow.next;
26 fast = fast.next;
27 }
28 fast.next = head;
29 head = slow.next;
30 slow.next = null;
31 return head;
32 }
15、排序链表
1 public ListNode sortList(ListNode head) {
2 if (head == null || head.next == null) {
3 return head;
4 }
5 ListNode tail = head;
6 ListNode tmp = head;
7 ListNode cur = head.next;
8 while (cur != null) {
9 tmp = head;
10 if (cur.val >= tail.val) { // 尾插
11 tail = cur;
12 cur = cur.next;
13 continue;
14 }
15 if (cur.val < head.val) { // 头插
16 tail.next = cur.next;
17 cur.next = head;
18 head = cur;
19 cur = tail.next;
20 continue;
21 }
22 while (tmp != tail && tmp.next.val < cur.val) {
23 tmp = tmp.next;
24 }
25 tail.next = cur.next;
26 cur.next = tmp.next;
27 tmp.next = cur;
28 cur = tail.next;
29 }
30 return head;
31 }
16、重排链表
1 public void reorderList(ListNode head) {
2 if (head == null || head.next == null || head.next.next == null) {
3 return;
4 }
5 int length = 0;
6 ListNode slow = head;
7 ListNode fast = head;
8 while (fast.next != null && fast.next.next != null) {
9 slow = slow.next;
10 fast = fast.next.next;
11 }
12 ListNode lasthead = slow.next; // 指向后半部分链表【待逆置的链表】
13 slow.next = null;
14 // 逆置后半部分链表
15 fast = lasthead.next;
16 ListNode tmp = fast;
17 lasthead.next = null;
18 while (fast != null) {
19 tmp = fast.next;
20 fast.next = lasthead;
21 lasthead = fast;
22 fast = tmp;
23 }
24 // 合并两个链表
25 fast = lasthead.next;
26 slow = head;
27 while (lasthead != null && slow != null) {
28 fast = lasthead.next;
29 lasthead.next = slow.next;
30 slow.next = lasthead;
31 lasthead = fast;
32 slow = slow.next.next;
33 }
34 }
以上是部分链表编程题,后续我还会放置更多的编程题及其答案,上述代码有什么不对的地方或者可以优化的地方,欢迎大家指出~~