玩转算法面试之链表
206 Reverse Linked List
- 反转链表。
- 一般遇到这种题,入门的大概思路是利用栈存储,然后再反向弹出赋值更新(改变链表中的值),不过这种思路是错误的。
- 那我先把头结点指向Null? 错,因为这样我们就拿不到2这个节点了。
- 我们需要三个指针来帮我们解决问题。(pre,cur,next)三个节点依次向前移动
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let pre = null
while (head) {
// 保存下一个结点
next = head.next
// 反转指针方向
head.next = pre
// 节点递增
pre = head
head = next
}
return pre
};
92. Reverse Linked List II
反转一个链表从m到n的元素。
如对于链表1->2->3->4->5->NULL,m=2,n=4。则返回链表1->4->3->2->5->NULL
- m和n超过链表范围怎么办? m和n是负值怎么办?
- m>n怎么办?
- m=1.或者n是最后一个
var reverseBetween = function(head, m, n) {
if(m >= n) {
return head;
}
var dummy = new ListNode(0); //通过构建listNode,处理m==1的情况
dummy.next = head;
head = dummy;
// 移动head到m-1的node;
for(var i = 0; i < m - 1; i++) {
head = head.next;
}
var pre = head.next;
var cur = pre.next;
for(i = 0; i < n - m; i++) {
var tmp = cur.next;
cur.next = pre;
pre = cur;
cur = tmp;
}
// head.next仍然指向m节点
head.next.next = cur;
head.next = pre;
return dummy.next;
};
83. Remove Duplicates from Sorted List
给出一个有序链表,删除其中所有重复元素,使得每个元素只保留一次。
- 如1->1->2,返回1->2
- 如1->1->2->3->3,返回1->2->3
86. Partition List
给出一个链表以及一个数x,将链表重新整理,使得小于x的元素在前;大于等于x的元素在后。
- 如1->4->3->2->5->2,×=3
- 返回1->2->2->4->3->5
- 左边和右边的顺序是任意还是需要保持原有链表的顺序
328. Odd Even Linked List
给出一个链表,将链表重新整理,使得所有索引为奇数的节点排在索引为偶数的节点前面。
- 如1->2->3->4->5->NULL
- 返回1->3->5->2->4->NULL
- 第一个节点的索引为1
- 奇数索引的节点和偶数索引的节点在重新整理后要保持相对顺序。
2. Add Two Numbers
给出两个非空链表,表示两个非负整数。其中每一个整数的各位数字以逆序存储,返回这两个整数相加所代表的链表。
- 如342+465=807
- 则给出2->4->3和5->6->4,返回7->0->8
- 数字中是否有前置的零。(除零以外,没有前置零)
- 当我们遇到字符串表示数字的情况时,要考虑负数。本文因为已经支持非负整数
445. Add Two Numbers II
给出两个非空链表,表示两个非负整数。其中每一个整数的各位数字以顺序存储,返回这两个整数相加所代表的链表。
- 如342+465=807
- 则给出3->4->2和4->6->5,返回8->0->7
- 不允许修改输入的链表
- 使用辅助数据结构
设立链表的虚拟头节点
203. Remove Linked List Elements
在链表中删除值为val的所有节点
- 如1->2->6->3->4->5->6->NULL,要求删除值为6的节点
- 返回1->2->3->4->5->NULL
- 对删除第一个元素不适用,不过我们可以拿出来单独判断头节点,但是这样就产生了两个删除逻辑,所以这个时候就需要dummy虚拟节点,这样对链表中的所有节点都可以统一了
var removeElements = function(head, val) {
if(head === null){
return head;
}
var dummy = new ListNode(-1);
dummy.next = head;
prev = dummy;
cur = head;
while(prev !== null && prev.next !== null){
// 如果当前元素等于要删除元素,删除
if(cur.val === val) {
prev.next = cur.next;
cur = prev.next;
} else {
prev = cur;
cur = cur.next;
}
}
return dummy.next;
};
虚拟头节点技巧巩固
82. Remove Duplicates from Sorted Listed II
给定一个有序链表,将其中有重复的元素全部删除。
- 如1->2->3->3->4->4->5,返回1->2->5
- 如1->1->1->2->3,返回2->3
21. Merge Two Sorted Lists
merge两个有序的链表
24. Swap Nodes in Pairs
给定一个链表,对于每两个相邻的节点,交换其位置。
- 如:链表为1->2->3->4->NULL
- 返回:2->1->4->3->NULL
- 只能对节点进行操作,不能修改节点的值
- 下图next是不必要指针,但是去除优化效果不大
var swapPairs = function(head) {
var dummy = new ListNode(0);
dummy.next = head;
var n1 = dummy;
var n2 = head;
// 确认还有节点可以交换
while(n2 !== null && n2.next !== null){
// 保存next节点,防止丢失
var nextStart = n2.next.next;
// 交换
n1.next = n2.next;
n1.next.next = n2;
n2.next = nextStart;
n1 = n2;
n2 = n2.next;
}
return dummy.next;
};
25. Reverse Nodes in k-Group
给定一个链表,每k个节点为一组,反转每一组的k个节点。k为正整数且小于等于链表长度。如果链表长度不是k的整数倍,剩余部分不需要进行反转。如:1->2->3->4->5->NULL
- 若k=2,则结果为:2->1->4->3->5->NULL
- 若k=3,则结果为:3->2->1->4->5->NULL
147. Insertion Sort List
为一个链表进行插入排序
148. Sort List
写一个排序算法,用0(nlogn)的时间复杂度为一个链表进行排序
归并排序
237. Delete Node in a Linked List
给定链表中的一个节点,删除该节点
难点:不可能拿到删除节点的前一个节点
解决思路: deleteNode = deleteNode->next, 然后删除deleteNode->next(老办法)
var deleteNode = function(node) {
if(node == null) return;
if(node.next === null){
node.val = null;
return;
}
node.val = node.next.val;
node.next = node.next.next;
};
双指针技术
19. Remove Nth Node From End of List
给定一个链表,删除倒数第n个节点
- 如:1->2->3->4->5->NULL,n=2
- 返回:1->2->3->5
- n从0计还是从1计
- n不合法,负数或者大于链表长度如何处理(保证n合法)
解法1:先遍历一遍计算链表长度;再遍历一遍删除倒数第n个节点
- 遍历两遍链表。能否只遍历一遍链表?
- 借助两个指针: 两个指针间的距离相等
var removeNthFromEnd = function(head, n) {
var n1 = new ListNode();
var n2 = new ListNode();
var dummy = n2;
n1.next = head;
n2.next = head;
// 这里判断n1是为了防止传入的n比链表总长度还要长
while(n > 0 && n1){
n1 = n1.next;
n--;
}
// 说明n确实比链表还要长。
if(n > 0){
return head;
}
// 经过上面的循环,n1和n2已经相差了n个结点
while(n1 && n1.next){
n1 = n1.next;
n2 = n2.next;
}
// 删除
n2.next = n2.next.next;
return dummy.next;
};
61. Rotate List
给定一个链表,让这个链表向右旋转k位。其中k为非负数。
如:1->2->3->4->5->NULL,k=2
- 第一次旋转:5->1->2->3->4->NULL
- 第二次旋转:4->5->1->2->3->NULL
143.Reorder List
给定一个链表L(0)>L(1)>L(2)>.…>L(n-1)>L(n)
将其变为L(O)>L(n)->L(1)->L(n-1)->L(2)->L(n-2)……的形式
- 链表无法随机访问数据,如何获得中间的元素?
- 两次遍历可以,但是一次遍历怎么获取?
234.Palindrome Linked List
给一个链表,判断这个链表是否为回文链表。
- 能否使用0(1)的空间复杂度解决问题?
共同学习,写下你的评论
评论加载中...
作者其他优质文章