链表
我的博客:blog.koreyoshi.work
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构
剑指offer 和 LeetCode 中的相关题目做一个汇总,感谢尾尾部落,从部落中学习转载。
1.反转链表
题目描述:输出一个单链表的逆序反转后的链表。 解题思路:用三个临时指针 prev、cur、next 在链表上循环一遍即可。
public ListNode preListNode(ListNode node){
ListNode head = node;
ListNode pre = head.next;
while(pre != null){
ListNode tmp = pre.next;
// 接在后面
pre.next = head;
// 给回head
head = pre;
pre = tmp;
}
node.next = null;
return head;
}
2.旋转链表(将链表向右旋转 K 个位置)
题目描述:给定一个单链表,设计一个算法实现链表向右旋转 K 个位置。 举例: 给定 1->2->3->4->5->6->NULL, K=3 则4->5->6->1->2->3->NULL 解题思路:
-
方法一 双指针,快指针先走k步,然后两个指针一起走,当快指针走到末尾时,慢指针的下一个位置是新的顺序的头结点,这样就可以旋转链表了。
-
方法二 先遍历整个链表获得链表长度n,然后此时把链表头和尾链接起来,在往后走n – k % n个节点就到达新链表的头结点前一个点,这时断开链表即可。
方法二代码:
public ListNode 旋转链表(ListNode node, int k){
if (node == null){
return null;
}
ListNode pre = node;
int n = 1;
while (pre.next != null){
n++;
pre = pre.next;
}
pre.next = node;
int m = n - k%n;
for (int i = 0; i < m; i++){
pre = pre.next;
}
ListNode newNode = pre.next;
pre.next = null;
return newNode;
}
3.求单链表的中间节点
题目描述:求单链表的中间节点,如果链表的长度为偶数,返回中间两个节点的任意一个,若为奇数,则返回中间节点。 解题思路:快慢指针,慢的走一步,快的走两步,当快指针到达尾节点时,慢指针移动到中间节点。
public static ListNode 单链表的中间节点(ListNode head){
if (head == null){
return null;
}
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
4.链表划分
题目描述: 给定一个单链表和数值x,划分链表使得所有小于x的节点排在大于等于x的节点之前。
摘除法:
public ListNode 划分(ListNode head, int k){
ListNode rightDummy = new ListNode(0);
ListNode leftDummy = new ListNode(0);
ListNode left = leftDummy, right = rightDummy;
while (head != null){
if (head.val < k){
left.next = head;
left = head;
} else {
right.next = head;
right = head;
}
head = head.next;
}
right.next = null;
left.next = rightDummy.next;
return leftDummy.next;
}
5.链表求和
题目描述:你有两个用链表代表的整数,其中每个节点包含一个数字。数字存储按照在原来整数中相反的顺序,使得第一个数字位于链表的开头。写出一个函数将两个整数相加,用链表形式返回和。 解题思路:做个大循环,对每一位进行操作:
当前位:(A[i]+B[i])%10 进位:(A[i]+B[i])/10
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode d = new ListNode(0);
ListNode res = d;
int sum = 0;
ListNode l = l1;
ListNode r = l2;
while (l != null || r != null){
if (l != null){
sum += l.val;
l = l.next;
}
if (r != null){
sum += r.val;
r = r.next;
}
res.next = new ListNode(sum%10);
sum = sum/10;
res = res.next;
}
if (sum != 0){
res.next = new ListNode(sum%10);
}
return d.next;
}
6.单链表排序
题目描述:在O(nlogn)时间内对链表进行排序。