出一些算法笔试题。
给定一个单链表的头结点 head,长度为 n,反转该链表后,返回新链表的表头。
数据范围: 0 ≤ n ≤ 1000
要求:空间复杂度 O(1) ,时间复杂度 O(n)。
function reverseList(head) {if (head == null || head.next == null) {return head;}let prev = null; // 前一个节点let current = head; // 当前节点let next = null;while (current != null) {// 记录下一个节点next = current.next;// 将当前节点的next指向前一个节点,实现反转current.next = prev;// 移动prev和current一格prev = current;current = next;}return prev;}
将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转。
要求:时间复杂度 O(n),空间复杂度 O(1)。
class ListNode {constructor(val, next = null) {this.val = val;this.next = next;}}// [0], 1, 2, 3, 4, 5;function reverseBetween(head, m, n) {if (head === null || head.next === null || m === n) {return head;}// 创建一个虚拟头结点,作为链表的头部,简化边界处理const dummy = new ListNode(0);dummy.next = head;// 设置指针,指向虚拟节点let pre = dummy;for (let i = 1; i < m; i++) {// 翻转左区间pre = pre.next;}// 翻转的第一个节点let cur = pre.next;for (let i = m; i < n; i++) {let temp = cur.next; // 3,cur 的下一个节点cur.next = temp.next; //4,cur 指针,向后移2temp.next = pre.next; // 2,next 指针,向前移1pre.next = temp; // 3,pre 指针,向后移2}return dummy.next;}
输入两个递增的链表,单个链表的长度为 n,合并这两个链表并使新链表中的节点仍然是递增排序的。
如输入 {1,3,5},{2,4,6} 时,合并后的链表为 {1,2,3,4,5,6}。
function mergeTwoLists(l1, l2) {// 创建一个新的虚拟头结点const dummy = new ListNode(0);let current = dummy;// 当两个链表都不为空时进行合并while (l1 && l2) {if (l1.val < l2.val) {current.next = l1;l1 = l1.next;} else {current.next = l2;l2 = l2.next;}current = current.next;}// 如果其中一个链表已经为空,则将另一个链表剩下的部分直接连接到结果链表上current.next = l1 || l2;// 返回合并后的新链表的头结点return dummy.next;}