数据结构------链表

什么是链表

非连续非顺序的存储结构,以节点直接的指针指向进行遍历

链表的特性

1.无法随机读取元素,只能通过指针遍历,查找的时间复杂度O(n)
2.元素的删除和新增时间复杂度仅为O(1)

元素的插入和删除

存在链表1->2->3->4要在2和3之间插入节点,只需要将2的next指向newNode,将newNode的next指向3即可,如果要删除2节点,只需要将1的next指向3,2的next指向null。
代码实现:

function ListNode(val){
	this.val = val;
	this.next = null;
}
// 将node插入到指定的indexNode之后
function insertNode(indexNode,node){
	let next = indexNode.next;
	indexNode.next = node;
	node.next = next;
}
// 删除node节点
function deleteNode(head,node){
	let temp = head,
		pre = null;
	while(temp){
		if(temp === node){
			if(!pre){
				pre.next = temp.next;
				node.next = null;
			}
		}
		pre = temp;
		temp = temp.next;
	}
}

leetcode题目

19. 删除链表的倒数第N个节点

题目描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:

给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.

说明:
给定的 n 保证是有效的。

思路:先遍历整个链表排列成一个数组,然后直接删除倒数第n个
我的代码:

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
var removeNthFromEnd = function(head, n) {
    var nodeList = [head],
        next=head.next;
    while(next){
        nodeList.push(next);
        next = next.next;
    };
    //删除头部
    if(nodeList.length === n){
        return head.next;
    }
    if(nodeList[nodeList.length-n-1]){
        nodeList[nodeList.length-n-1].next = nodeList[nodeList.length-n].next;
    }
    nodeList[nodeList.length-n].next = null;
    if(nodeList.length === 1){
        return null;
    }
    return head;
};
23.合并k和排序链表

合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

思路:
先用bfs宽度遍历每个链条同级的元素按顺序放进一个list中,然后按list的顺序生成新的链表

我的代码:

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function(lists) {
    if(!lists||!lists.length){
        return null;
    }
    // bfs获取所有节点的集合
    var newList = [],
        head = null,
        tempNode;
    bfs(lists,newList);
    newList.sort((node1,node2)=>node1.val-node2.val);
    head = newList[0];
    tempNode = head;
    for(let i=1;i<newList.length;i++){
        tempNode.next = newList[i];
        tempNode = newList[i];
    }
    return head || null;
};
var bfs = function(lists,newList){
    if(!lists || !lists.length){
        return;
    }else{
        let next = [];
        for(let i=0;i<lists.length;i++){
            let node = lists[i];
            if(node){
                if(node.next){
                    next.push(node.next);
                }
                newList.push(new ListNode(node.val));
            }
        }
        bfs(next,newList);
    }
}
25. K 个一组翻转链表

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5

说明 :
你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

思路:
逐个遍历,记住每组第一个元素,当遍历到个数为k时对这一组进行交换,返回当前组的最后一个最新的元素和下一组的第一个元素,如果存在上一组的第一个元素那么就将其和当前组的最后一个元素进行连接。

我的代码:

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var reverseKGroup = function(head, k) {
    if(k===1){ 
        return head;
    }
    if(!canReverse(head,k)){
        return head;
    }
    let node = head,
        preNode = node,
        realHead = null,
        temp;
    while(node!==null){
        if(!canReverse(node,k)){
            preNode.next = node;
            return realHead;
        }
        temp = reverse(node,k);
        if(!realHead){
            // 真正的头是第一次翻转组的最后一个
            realHead = temp[0];
        }else{
            // 上一组的第一个指向当前组的最后一个
            preNode.next = temp[0];
            preNode = node;
        }
        node = temp[1];
    }
    return realHead;
};

var reverse = function(node,k){
    let pre = null,
        next,
        curr = node,
        i=1;
    while(i<=k&&curr!==null){
    	// 节点交换
        next = curr.next;
        curr.next = pre;
        pre = curr;
        curr = next;
        i++;
    }
    return [pre,curr];
}
var canReverse = function(node,k){
    let num=0,
        temp = node;
    while(temp&&num<k){
        num++;
        temp = temp.next;
    }
    if(num===k){
        return true;
    }else{
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值