您的位置:首页 > 其它

LeetCode链表部分题目思路总结

2018-05-21 20:22 344 查看

反转链表

92. 反转链表II
public ListNode reverseBetween(ListNode head, int m, int n) {
// 找到第m个节点的前一个节点 prev, 当前正在处理的节点curr(即将当前节点的下一个节点,放到prev 的下一个节点);
//直到当前节点到达第n 个节点为止
if(head == null)
return null;
ListNode newhead = new ListNode(0);
newhead.next = head;
ListNode prev = newhead;
int i = 1;
while(prev.next != null && i < m) {
// 找 第m个节点
prev = prev.next;
i++;
}
// 此时 prev 即指向 第 m - 1 个节点,
ListNode first = prev.next;
ListNode second = first.next;
while(first.next != null && i < n) {
// 开始交换
first.next = second.next;
second.next = prev.next;
prev.next = second;
second = first.next;
i++;
}
return newhead.next;
}
206. 反转链表
public ListNode reverseList(ListNode head) {

// 思路: 新建头结点,使其指向head, 交换 head  和 head 的下一个节点;
//此时 前两个节点已经 逆序, 继续将head 的下一个节点放到新的头结点的下一个节点;
//重复操作, 直到 head 的下一个节点为空为止;
if(head == null)
return null;
ListNode newhead = new ListNode(0);
ListNode curr;
newhead.next = head;
while(head.next != null) {
curr = head.next;
//交换两节点
head.next = curr.next;
curr.next = newhead.next;
newhead.next = curr;
}
return newhead.next;
}
25. k个一组翻转链表
public ListNode reverseKGroup(ListNode head, int k) {
// 先遍历一次 看有多少个节点, 再 每K个一组 翻转
ListNode newhead = new ListNode(0);
newhead.next = head;
ListNode prev = newhead;  // 记录待翻转部分的前一个节点
ListNode tmp = head;
int i = 0;
//  遍历 看 有多少个节点 用i 记录 原节点数
while(tmp != null) {
i++;
tmp = tmp.next;
}
while(i >= k) {
// 条件成立才会翻转
for(int j = 0; j < k - 1; j++) {
// head 记录当前值, after 记录head 的 下一个值
ListNode after = head.next;
head.next = after.next;
after.next = prev.next;
prev.next = after;
}
prev = head;
head = head.next;
i -= k;
}
return newhead.next;
}
2.两数相加
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
// 两数之和, 两个链表独立操作, 需要新的链表存储结果
ListNode newhead = new ListNode(0);
ListNode curr = newhead;
int sum = 0; // 记录 两数之和
while(l1 != null || l2 != null) {
sum /= 10; // 进位
if(l1 != null) {
sum += l1.val;
l1 = l1.next;
}
if(l2 != null) {
sum += l2.val;
l2 = l2.next;
}
curr.next = new ListNode(sum % 10);
curr = curr.next;
}
// 判断最后一次相加之后是否有进位
if(sum > 9)
curr.next = new ListNode(1);
return newhead.next;
}
445. 两数相加 II 考虑 栈**
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
if (l1 == null)
return l2;
if (l2 == null)
return l1;
Stack<Integer> s1 = new Stack<>();
Stack<Integer> s2 = new Stack<>();
while (l1 != null) {
s1.push(l1.val);
l1 = l1.next;
}
while (l2 != null) {
s2.push(l2.val);
l2 = l2.next;
}
int sum = 0;
// head的下一个结点为curNode
ListNode curNode = new ListNode(0);
while (!s1.isEmpty() || !s2.isEmpty()) {
if (!s1.isEmpty())
sum += s1.pop();
if (!s2.isEmpty())
sum += s2.pop();
// head.val存储进制位,head.val可能为0
ListNode head = new ListNode(sum / 10);
// curNode存储结果
curNode.val = sum % 10;
head.next = curNode;
// curNode往前移动,指向head
curNode = head;
// 此时sum存储的是进制位
// 下次计算需要用到
sum /= 10;
}
// 前导0的情况,
// curNode为head的引用,可能为0
if (curNode.val == 0)
curNode = curNode.next;
return curNode;
// 前导0的情况
// return curNode.val == 0 ?
// curNode.next : curNode;
}
23. 合并K个排序链表
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length == 0) {
return null;
}
// 控制 每隔  多少   合并一次   即 合并的 步长
for(int step = 1; step < lists.length; step *= 2) {
//  控制 合并后 链表 存放的 位置
for(int i = 0; i < lists.length; i += step * 2) {
if(i + step >= lists.length)
break; // 索引越界
lists[i] = mergeTwoLists(lists[i], lists[i + step]);
}
}
return lists[0];
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode newhead = new ListNode(-1);
ListNode c = newhead; // 记录当前节点
while(l1 != null || l2 != null) {
if(l2 == null || (l1 != null && l1.val < l2.val)) {   //  短路 或
c.next = l1;
l1 = l1.next;
}
else {
c.next = l2;
l2 = l2.next;
}
c = c.next;
}
return newhead.next;
}
19. 删除链表的倒数第N个节点思路: 记录倒数第N个节点的前一个节点; 为防止头结点被删除而找不到链表, 新建一个头结点,并令其下一个节点为链表的初始头结点; 双指针延迟启动, 待前一个指针到达链表的第N个节点时, 令后一个指针指向新的头结点, 并随着 前一个指针的移动而向后移动,直到前一个指针指向最后一个节点为止;
public ListNode removeNthFromEnd(ListNode head, int n) {
//   删除链表的  倒数  第  n 个 节点  一趟扫描
// 防止  头结点被删除
ListNode newhead = new ListNode(-1);
newhead.next = head;
ListNode p1 = newhead;
ListNode p2 = newhead;
for(; p1 != null; p1 = p1.next, n--) {
if(n < 0) {
p2 = p2.next;//  p2 记录待删除节点的前一个节点
}
}
p2.next = p2.next.next;
return newhead.next;
}
24. 两两交换链表中的节点思路: 记录 first, second, third 其中 second 和 third 为当前正在交换的节点
public ListNode swapPairs(ListNode head) {
// 当前节点   当前节点的 孩子  当前节点的  孙子
if(head == null) {
return null;
}
ListNode newhead = new ListNode(0);
ListNode first, second;
newhead.next = head;
ListNode current = newhead;
while(current.next != null && current.next.next != null) {
first = current.next;
second = current.next.next;
// 开始交换
first.next = second.next;
second.next = first;
current.next = second;

// 移动当前位置   为 待交换节点的  前一个
current = first;
}
return newhead.next;
}
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: